diff --git a/README.md b/README.md index e79c672..1bc16a7 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,57 @@ # Nerves -A termeal version with led strip on raspberry pi +A termeal version with neopixel led strip on raspberry pi (Raspberry Pi 1 is fine). + +Termeal : color depends on port number of sniffed packet. + +A change mode function is included but only scapy mode work yet. + +Neopixel strip (3 wires : 5V,GND,IN) : + +* Neopixel GPIO D18 #(-> pin 12) +* GND pin 9 +* 5 V pin 4 + +Physical buttons : + +* Func button : GPIO 23 (->pin 16) / GND pin 14 +* Down button : GPIO 24 (->pin 18) / GND pin 20 + + +# Control + +2 physical buttons and Webpage (browse to pi address) + # Install sudo apt install python3-pip + sudo pip3 install rpi_ws281x adafruit-circuitpython-neopixel + sudo python3 -m pip install --force-reinstall adafruit-blinka + sudo pip3 install scapy +For automatic shutdown : + +sudo nano /etc/sudoers + +add : + +pi raspberrypi =NOPASSWD: /usr/bin/systemctl poweroff + + +# Autorun + +To autorun nerves at boot time : + +cd nerves + +sudo cp /home/pi/nerves/autorun.conf /etc/supervisor/conf.d/ +sudo supervisorctl reload # Based on previous work : -https://github.com/loloster/termeal -https://github.com/s0r00t/sniffeal \ No newline at end of file +* https://github.com/loloster/termeal +* https://github.com/s0r00t/sniffeal \ No newline at end of file diff --git a/autorun.conf b/autorun.conf new file mode 100644 index 0000000..3b5a2af --- /dev/null +++ b/autorun.conf @@ -0,0 +1,6 @@ +[program:nerves] +autorestart = True +directory = /home/pi/nerves +user = pi +command = sh /home/pi/nerves/autorun.sh +environment = STNORESTART="1", HOME="/home/pi/nerves/" diff --git a/autorun.sh b/autorun.sh new file mode 100644 index 0000000..251b602 --- /dev/null +++ b/autorun.sh @@ -0,0 +1,4 @@ +#!/bin/bash +#sudo python3 /home/pi/nerves/ws.py & +#sudo python3 /home/pi/nerves/buttons.py & +sudo python3 /home/pi/nerves/nerves.py \ No newline at end of file diff --git a/buttons.py b/buttons.py new file mode 100644 index 0000000..5c9dede --- /dev/null +++ b/buttons.py @@ -0,0 +1,85 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + +''' + +Physical buttons handler for Nerves v0.1b + +Func button : GPIO 23 (->pin 16) / ground pin 14 +Down button : GPIO 24 (->pin 18) / ground 20 + +When button is pressed : button.value -> False + + +''' + +from time import sleep +import board +import digitalio +import leds + +crtfunc = 0 +funcs = [0,1,2] + +debug = 0 + +print("Loading Nerves buttons handler v0.1b") + +funcbutton = digitalio.DigitalInOut(board.D23) +funcbutton.direction = digitalio.Direction.INPUT +funcbutton.pull = digitalio.Pull.UP + +funcstate = True + +downbutton = digitalio.DigitalInOut(board.D24) +downbutton.direction = digitalio.Direction.INPUT +downbutton.pull = digitalio.Pull.UP + +def runforever(): + global crtfunc, funcstate + + while True: + + #print(funcbutton.value, funcstate, crtfunc, downbutton.value) + #print(funcbutton.value, funcstate) + + if not funcbutton.value: + + if debug > 0: + print("func button pressed : ", funcbutton.value, funcstate ) + + sleep(0.2) + + # Launch on button release + if funcbutton.value and funcstate == False : + + crtfunc +=1 + if crtfunc == len(funcs): + crtfunc = 0 + print('Launch func', crtfunc) + if crtfunc == 0: + leds.mode = 0 + if crtfunc == 1: + leds.mode = 1 + + sleep(0.2) + + funcstate = funcbutton.value + + if not downbutton.value: + if debug > 0: + print("down button pressed") + + import os + print('will shutdown...') + leds.mode = -1 + leds.cls() + os.system("systemctl poweroff") + + sleep(0.005) + + +if __name__ == '__main__': + + runforever() \ No newline at end of file diff --git a/cls.py b/cls.py new file mode 100644 index 0000000..bacdf69 --- /dev/null +++ b/cls.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' + + +SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +SPDX-License-Identifier: MIT + +''' + +# Simple test for NeoPixels on Raspberry Pi +import time +import board +import neopixel + + +# Choose an open pin connected to the Data In of the NeoPixel strip, i.e. board.D18 +# NeoPixels must be connected to D10, D12, D18 or D21 to work. +pixel_pin = board.D18 + +# The number of NeoPixels +num_pixels = 14 + +# The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed! +# For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW. +ORDER = neopixel.GRB + +pixels = neopixel.NeoPixel( + pixel_pin, num_pixels, brightness=0.2, auto_write=False, pixel_order=ORDER +) + +def cls(): + + print('Cls') + pixels.fill((0, 0, 0)) + pixels.show() + + +if __name__ == '__main__': + + cls() diff --git a/cls.sh b/cls.sh new file mode 100644 index 0000000..5ebbbc6 --- /dev/null +++ b/cls.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sudo python3 /home/pi/nerves/cls.py \ No newline at end of file diff --git a/down.sh b/down.sh new file mode 100644 index 0000000..d3835a9 --- /dev/null +++ b/down.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sudo shutdown -h now \ No newline at end of file diff --git a/leds.py b/leds.py index 64abbf6..b26b73e 100644 --- a/leds.py +++ b/leds.py @@ -1,16 +1,18 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - - ''' -sudo aot install python3-pip -sudo pip3 install rpi_ws281x adafruit-circuitpython-neopixel -sudo python3 -m pip install --force-reinstall adafruit-blinka +Neopixel GPIO D18 #(-> pin 12) +Ground pin 9 +5 V pin 4 + +Modes : + +-1 cls +0 Scappy +1 Rainbow -SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries -SPDX-License-Identifier: MIT ''' @@ -22,11 +24,31 @@ import neopixel # Choose an open pin connected to the Data In of the NeoPixel strip, i.e. board.D18 # NeoPixels must be connected to D10, D12, D18 or D21 to work. -pixel_pin = board.D18 +pixel_pin = board.D18 #(-> pin 12) # The number of NeoPixels -num_pixels = 6 +num_pixels = 14 +palette = [(0,0,0), + (255,0,0), + (0,255,0), + (0,0,255), + (255,255,0), + (0,255,255), + (255,0,255), + (192,192,192), + (128,128,128), + (128,0,0), + (128,128,0), + (0,128,0), + (128,0,128), + (0,128,128), + (0,0,128) + ] + +nbcolor = len(palette) +#print(nbcolor, "colors") +#print(palette) # The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed! # For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW. ORDER = neopixel.GRB @@ -35,6 +57,8 @@ pixels = neopixel.NeoPixel( pixel_pin, num_pixels, brightness=0.2, auto_write=False, pixel_order=ORDER ) +# mode 0 : scapy +mode = 0 def wheel(pos): # Input a value 0 to 255 to get a color value. @@ -57,18 +81,57 @@ def wheel(pos): b = int(255 - pos * 3) return (r, g, b) if ORDER in (neopixel.RGB, neopixel.GRB) else (r, g, b, 0) - +# rainbow demo def rainbow_cycle(wait): - for j in range(255): - for i in range(num_pixels): - pixel_index = (i * 256 // num_pixels) + j - pixels[i] = wheel(pixel_index & 255) - pixels.show() - time.sleep(wait) + + if mode == 1: + for j in range(255): + for i in range(num_pixels): + pixel_index = (i * 256 // num_pixels) + j + pixels[i] = wheel(pixel_index & 255) + pixels.show() + time.sleep(wait) + +# rainbow mode +def rainbow_mode(wait = 0.001): + + if mode == 1: + for j in range(255): + for i in range(num_pixels): + pixel_index = (i * 256 // num_pixels) + j + pixels[i] = wheel(pixel_index & 255) + pixels.show() + time.sleep(wait) + +def cls(): + + print('Cls') + mode = -1 + pixels.fill((0, 0, 0)) + pixels.show() + +def ledscls(): + + print('Cls') + pixels.fill((0, 0, 0)) + pixels.show() + +def display(colors): + + print("Incoming generated colors :",colors) + for pixel in range(num_pixels): + #print(pixel, colors[pixel], palette[colors[pixel]] ) + pixels[pixel] = palette[colors[pixel]] + #print("pixels array :",pixels) + pixels.show() -while True: +def demo(): + global mode + + ledscls() # Comment this line out if you have RGBW/GRBW NeoPixels + print("Demo.") pixels.fill((255, 0, 0)) # Uncomment this line if you have RGBW/GRBW NeoPixels # pixels.fill((255, 0, 0, 0)) @@ -89,4 +152,11 @@ while True: pixels.show() time.sleep(1) + mode = 1 rainbow_cycle(0.001) # rainbow cycle with 1ms delay per step + + ledscls() + +if __name__ == '__main__': + + demo() diff --git a/nerves.py b/nerves.py index c1938f9..1c9ebe3 100644 --- a/nerves.py +++ b/nerves.py @@ -5,8 +5,9 @@ Nerves v 0.1 -A termeal version with led strip on raspberry pi +A termeal version with fiber optics on raspberry pi +goes with leds mode 0 sniff packets from interface en0 using python module scapy (2.3.1) generate led color for bhoreal in usb midi mode depending on packet port number @@ -26,91 +27,205 @@ log.infog("Nerves") log.infog("v0.1b") print("Loading...") -from OSC3 import OSCClient, OSCMessage +import adafruit_blinka.agnostic as agnostic +import board +import sys + +print( + "Found system type: %s (sys.platform %s implementation %s) " + % (agnostic.board_id, sys.platform, sys.implementation.name) +) + from sys import platform from time import sleep import types import random from scapy.all import * +from threading import Thread +import traceback -import argparse - -argsparser = argparse.ArgumentParser(description="Nerves v0.1") -argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output") -args = argsparser.parse_args() - -verbose=args.verbose +import leds +import buttons +import ws -client = OSCClient() -msg = OSCMessage() +# from Adafruit_GPIO import Platform +# print("Platform = ", Platform.platform_detect(), Platform.pi_version()) + +#print("board contents: ", dir(board)) + + +nerves = [[0,7],[1,3],[2,9],[4,13],[5,11],[6,12],[8,10]] +influx = [0]*(len(nerves)*2) +print(influx) counter = 0 +import argparse +parser = argparse.ArgumentParser(description="A Scanner Interface Darkly") +parser.add_argument("-i","--interface", help="interface to scan") +parser.add_argument("-x","--xcol",help="number of columns (8 by default)",type=int) +parser.add_argument("-y","--ycol",help="number of rows (8 by default)",type=int) +parser.add_argument("-f","--filter",help="tcpdump filter") +parser.add_argument("-c","--color",help="number of color",type=int) +parser.add_argument("-d","--display",help="type of side display",choices=["colors", "ports"]) +parser.add_argument("-epi","--ephemeralportmin",help="ephemeral port min to exclude (32768 by default), set to 65536 to include all ports",type=int) +parser.add_argument("-epa","--ephemeralportmax",help="ephemeral port max to exclude (61000 by default)",type=int) +args = parser.parse_args() + +if args.xcol: + xmax=args.xcol +else: + xmax=8 + +if args.ycol: + ymax=args.ycol +else: + ymax=8 + +if args.color: + nbcolor=args.color +else: + nbcolor=15 + +if args.display: + sidedisplay=args.display +else: + sidedisplay="ports" + +if args.ephemeralportmin: + ephemeralportmin = args.ephemeralportmin +else: + ephemeralportmin = 32768 + +if args.ephemeralportmax: + ephemeralportmax = args.ephemeralportmax +else: + ephemeralportmax = 61000 + + def sendled(zzzport): global counter - zzz = zzzport % 127 - # zzz = led color - msg = OSCMessage() - msg.setAddress("/bhoreal/in") - msg.append(counter) - msg.append(zzz) - try: - client.sendto(msg, ('127.0.0.1', 9002)) - msg.clearData() - except: - print('Connection refused') - pass - sleep(0.001) - counter += 1 - if counter > 63: + #print("nerve",counter) + zzz = zzzport % leds.nbcolor # zzz = led color + + influx[nerves[counter][0]] = zzz + influx[nerves[counter][1]] = zzz + #print("nerve",counter,"influx", influx) + + leds.display(influx) + + #print(len(nerves), "nerves") + if counter +1 == len(nerves): counter = 0 - - + else: + counter += 1 + #print("next nerve", counter) def print_summary(pkt): - if IP in pkt: - ip_src=pkt[IP].src - ip_dst=pkt[IP].dst - - - if TCP in pkt: - tcp_sport=pkt[TCP].sport - tcp_dport=pkt[TCP].dport - if tcp_sport < 50000: - print (" IP src " + str(ip_src) + " TCP sport " + str(tcp_sport) ) - sendled(tcp_sport) - if tcp_dport < 50000: - print (" IP dst " + str(ip_dst) + " TCP dport " + str(tcp_dport)) - sendled(tcp_dport) - if UDP in pkt: - udp_sport=pkt[UDP].sport - udp_dport=pkt[UDP].dport + if leds.mode == 0: - if udp_sport < 50000: - print (" IP src " + str(ip_src) + " UDP sport " + str(udp_sport) ) - sendled(udp_sport) + if IP in pkt: + ip_src=pkt[IP].src + ip_dst=pkt[IP].dst - if udp_dport < 50000: - print (" IP dst " + str(ip_dst) + " UDP dport " + str(udp_dport)) - sendled(udp_dport) + + if TCP in pkt: + tcp_sport=pkt[TCP].sport + tcp_dport=pkt[TCP].dport + + if tcp_sport < 50000: + print (" IP src " + str(ip_src) + " TCP sport " + str(tcp_sport) ) + sendled(tcp_sport) + if tcp_dport < 50000: + print (" IP dst " + str(ip_dst) + " TCP dport " + str(tcp_dport)) + sendled(tcp_dport) + + if UDP in pkt: + udp_sport=pkt[UDP].sport + udp_dport=pkt[UDP].dport + + if udp_sport < 50000: + print (" IP src " + str(ip_src) + " UDP sport " + str(udp_sport) ) + sendled(udp_sport) + + if udp_dport < 50000: + print (" IP dst " + str(ip_dst) + " UDP dport " + str(udp_dport)) + sendled(udp_dport) - if ARP in pkt and pkt[ARP].op in (1,2): - print (" ARP") - sendled(67) + if ARP in pkt and pkt[ARP].op in (1,2): + print (" ARP") + sendled(67) def handle_error(self,request,client_address): # All callbacks pass +''' +def main(): + + print("Testing leds...") + leds.cls() + leds.demo() + leds.cls() + if platform == 'darwin': - sniff(iface='en0', prn=print_summary, store=0) + print("Running on", platform, "-> en0") + #sniff(iface='en0', prn=print_summary, store=0) + sniff(iface='en0', prn=print_summary, store=0,filter=args.filter) + else: + print("Running on", platform, "-> eth0") sniff(iface='eth0', prn=print_summary, store=0) +''' + +def main(): + + ws.Start(ws.serverIP, ws.wsPORT) + + try: + + ws_thread = Thread(target=ws.runforever, args=()) + ws_thread.setDaemon(True) + ws_thread.start() + + print("Launching buttons thread...") + buttons_thread = Thread(target=buttons.runforever, args=()) + buttons_thread.setDaemon(True) + buttons_thread.start() + + ws.sendWSall("/players Demo") + print("Testing leds...") + leds.cls() + leds.demo() + leds.cls() + + # Start sniffing + leds.mode = 0 + ws.sendWSall("/players Sniffing") + if platform == 'darwin': + print("Running on", platform, "-> en0") + #sniff(iface='en0', prn=print_summary, store=0) + sniff(iface='en0', prn=print_summary, store=0,filter=args.filter) + + else: + print("Running on", platform, "-> eth0") + sniff(iface='eth0', prn=print_summary, store=0) + except Exception: + traceback.print_exc() + + finally: + + ws_thread.join() + buttons_thread.join() + +if __name__ == '__main__': + + main() diff --git a/websocket_server.py b/websocket_server.py new file mode 100755 index 0000000..9d1af5c --- /dev/null +++ b/websocket_server.py @@ -0,0 +1,371 @@ +# Author: Johan Hanssen Seferidis +# License: MIT + +import sys +import struct +from base64 import b64encode +from hashlib import sha1 +import logging +from socket import error as SocketError +import errno + +if sys.version_info[0] < 3: + from SocketServer import ThreadingMixIn, TCPServer, StreamRequestHandler +else: + from socketserver import ThreadingMixIn, TCPServer, StreamRequestHandler + +logger = logging.getLogger(__name__) +logging.basicConfig() + +''' ++-+-+-+-+-------+-+-------------+-------------------------------+ + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-------+-+-------------+-------------------------------+ +|F|R|R|R| opcode|M| Payload len | Extended payload length | +|I|S|S|S| (4) |A| (7) | (16/64) | +|N|V|V|V| |S| | (if payload len==126/127) | +| |1|2|3| |K| | | ++-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + +| Extended payload length continued, if payload len == 127 | ++ - - - - - - - - - - - - - - - +-------------------------------+ +| Payload Data continued ... | ++---------------------------------------------------------------+ +''' + +FIN = 0x80 +OPCODE = 0x0f +MASKED = 0x80 +PAYLOAD_LEN = 0x7f +PAYLOAD_LEN_EXT16 = 0x7e +PAYLOAD_LEN_EXT64 = 0x7f + +OPCODE_CONTINUATION = 0x0 +OPCODE_TEXT = 0x1 +OPCODE_BINARY = 0x2 +OPCODE_CLOSE_CONN = 0x8 +OPCODE_PING = 0x9 +OPCODE_PONG = 0xA + + +# -------------------------------- API --------------------------------- + +class API(): + + def run_forever(self): + try: + logger.info("Listening on port %d for clients.." % self.port) + self.serve_forever() + except KeyboardInterrupt: + self.server_close() + logger.info("Server terminated.") + except Exception as e: + logger.error(str(e), exc_info=True) + exit(1) + + def new_client(self, client, server): + pass + + def client_left(self, client, server): + pass + + def message_received(self, client, server, message): + pass + + def set_fn_new_client(self, fn): + self.new_client = fn + + def set_fn_client_left(self, fn): + self.client_left = fn + + def set_fn_message_received(self, fn): + self.message_received = fn + + def send_message(self, client, msg): + self._unicast_(client, msg) + + def send_message_to_all(self, msg): + self._multicast_(msg) + + +# ------------------------- Implementation ----------------------------- + +class WebsocketServer(ThreadingMixIn, TCPServer, API): + """ + A websocket server waiting for clients to connect. + + Args: + port(int): Port to bind to + host(str): Hostname or IP to listen for connections. By default 127.0.0.1 + is being used. To accept connections from any client, you should use + 0.0.0.0. + loglevel: Logging level from logging module to use for logging. By default + warnings and errors are being logged. + + Properties: + clients(list): A list of connected clients. A client is a dictionary + like below. + { + 'id' : id, + 'handler' : handler, + 'address' : (addr, port) + } + """ + + allow_reuse_address = True + daemon_threads = True # comment to keep threads alive until finished + + clients = [] + id_counter = 0 + + def __init__(self, port, host='127.0.0.1', loglevel=logging.WARNING): + logger.setLevel(loglevel) + TCPServer.__init__(self, (host, port), WebSocketHandler) + self.port = self.socket.getsockname()[1] + + def _message_received_(self, handler, msg): + self.message_received(self.handler_to_client(handler), self, msg) + + def _ping_received_(self, handler, msg): + handler.send_pong(msg) + + def _pong_received_(self, handler, msg): + pass + + def _new_client_(self, handler): + self.id_counter += 1 + client = { + 'id': self.id_counter, + 'handler': handler, + 'address': handler.client_address + } + self.clients.append(client) + self.new_client(client, self) + + def _client_left_(self, handler): + client = self.handler_to_client(handler) + self.client_left(client, self) + if client in self.clients: + self.clients.remove(client) + + def _unicast_(self, to_client, msg): + to_client['handler'].send_message(msg) + + def _multicast_(self, msg): + for client in self.clients: + self._unicast_(client, msg) + + def handler_to_client(self, handler): + for client in self.clients: + if client['handler'] == handler: + return client + + +class WebSocketHandler(StreamRequestHandler): + + def __init__(self, socket, addr, server): + self.server = server + StreamRequestHandler.__init__(self, socket, addr, server) + + def setup(self): + StreamRequestHandler.setup(self) + self.keep_alive = True + self.handshake_done = False + self.valid_client = False + + def handle(self): + while self.keep_alive: + if not self.handshake_done: + self.handshake() + elif self.valid_client: + self.read_next_message() + + def read_bytes(self, num): + # python3 gives ordinal of byte directly + bytes = self.rfile.read(num) + if sys.version_info[0] < 3: + return map(ord, bytes) + else: + return bytes + + def read_next_message(self): + try: + b1, b2 = self.read_bytes(2) + except SocketError as e: # to be replaced with ConnectionResetError for py3 + if e.errno == errno.ECONNRESET: + logger.info("Client closed connection.") + print("Error: {}".format(e)) + self.keep_alive = 0 + return + b1, b2 = 0, 0 + except ValueError as e: + b1, b2 = 0, 0 + + fin = b1 & FIN + opcode = b1 & OPCODE + masked = b2 & MASKED + payload_length = b2 & PAYLOAD_LEN + + if opcode == OPCODE_CLOSE_CONN: + logger.info("Client asked to close connection.") + self.keep_alive = 0 + return + if not masked: + logger.warn("Client must always be masked.") + self.keep_alive = 0 + return + if opcode == OPCODE_CONTINUATION: + logger.warn("Continuation frames are not supported.") + return + elif opcode == OPCODE_BINARY: + logger.warn("Binary frames are not supported.") + return + elif opcode == OPCODE_TEXT: + opcode_handler = self.server._message_received_ + elif opcode == OPCODE_PING: + opcode_handler = self.server._ping_received_ + elif opcode == OPCODE_PONG: + opcode_handler = self.server._pong_received_ + else: + logger.warn("Unknown opcode %#x." % opcode) + self.keep_alive = 0 + return + + if payload_length == 126: + payload_length = struct.unpack(">H", self.rfile.read(2))[0] + elif payload_length == 127: + payload_length = struct.unpack(">Q", self.rfile.read(8))[0] + + masks = self.read_bytes(4) + message_bytes = bytearray() + for message_byte in self.read_bytes(payload_length): + message_byte ^= masks[len(message_bytes) % 4] + message_bytes.append(message_byte) + opcode_handler(self, message_bytes.decode('utf8')) + + def send_message(self, message): + self.send_text(message) + + def send_pong(self, message): + self.send_text(message, OPCODE_PONG) + + def send_text(self, message, opcode=OPCODE_TEXT): + """ + Important: Fragmented(=continuation) messages are not supported since + their usage cases are limited - when we don't know the payload length. + """ + + # Validate message + if isinstance(message, bytes): + message = try_decode_UTF8(message) # this is slower but ensures we have UTF-8 + if not message: + logger.warning("Can\'t send message, message is not valid UTF-8") + return False + elif sys.version_info < (3,0) and (isinstance(message, str) or isinstance(message, unicode)): + pass + elif isinstance(message, str): + pass + else: + logger.warning('Can\'t send message, message has to be a string or bytes. Given type is %s' % type(message)) + return False + + header = bytearray() + payload = encode_to_UTF8(message) + payload_length = len(payload) + + # Normal payload + if payload_length <= 125: + header.append(FIN | opcode) + header.append(payload_length) + + # Extended payload + elif payload_length >= 126 and payload_length <= 65535: + header.append(FIN | opcode) + header.append(PAYLOAD_LEN_EXT16) + header.extend(struct.pack(">H", payload_length)) + + # Huge extended payload + elif payload_length < 18446744073709551616: + header.append(FIN | opcode) + header.append(PAYLOAD_LEN_EXT64) + header.extend(struct.pack(">Q", payload_length)) + + else: + raise Exception("Message is too big. Consider breaking it into chunks.") + return + + self.request.send(header + payload) + + def read_http_headers(self): + headers = {} + # first line should be HTTP GET + http_get = self.rfile.readline().decode().strip() + assert http_get.upper().startswith('GET') + # remaining should be headers + while True: + header = self.rfile.readline().decode().strip() + if not header: + break + head, value = header.split(':', 1) + headers[head.lower().strip()] = value.strip() + return headers + + def handshake(self): + headers = self.read_http_headers() + + try: + assert headers['upgrade'].lower() == 'websocket' + except AssertionError: + self.keep_alive = False + return + + try: + key = headers['sec-websocket-key'] + except KeyError: + logger.warning("Client tried to connect but was missing a key") + self.keep_alive = False + return + + response = self.make_handshake_response(key) + self.handshake_done = self.request.send(response.encode()) + self.valid_client = True + self.server._new_client_(self) + + @classmethod + def make_handshake_response(cls, key): + return \ + 'HTTP/1.1 101 Switching Protocols\r\n'\ + 'Upgrade: websocket\r\n' \ + 'Connection: Upgrade\r\n' \ + 'Sec-WebSocket-Accept: %s\r\n' \ + '\r\n' % cls.calculate_response_key(key) + + @classmethod + def calculate_response_key(cls, key): + GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' + hash = sha1(key.encode() + GUID.encode()) + response_key = b64encode(hash.digest()).strip() + return response_key.decode('ASCII') + + def finish(self): + self.server._client_left_(self) + + +def encode_to_UTF8(data): + try: + return data.encode('UTF-8') + except UnicodeEncodeError as e: + logger.error("Could not encode data to UTF-8 -- %s" % e) + return False + except Exception as e: + raise(e) + return False + + +def try_decode_UTF8(data): + try: + return data.decode('utf-8') + except UnicodeDecodeError: + return False + except Exception as e: + raise(e) diff --git a/ws.py b/ws.py new file mode 100644 index 0000000..bee6848 --- /dev/null +++ b/ws.py @@ -0,0 +1,216 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# -*- mode: Python -*- + +''' + +Nerves WS server v0.1b + +http page index.html get Server IP, Port from config.js + +''' + +#import socket +import types, json +import _thread, time + +from websocket_server import WebsocketServer +import argparse +import leds +import traceback + +debug = 1 +Players=0 +clientmode = False +broadcast = True + +# record current values +crtvalueMMO3 = [0] * 32 +crtfunc = 0 +funcs = [0,1,2] + + +print("") +print("Loading Nerves WS server v0.1b") +print ("Arguments parsing if needed...") +argsparser = argparse.ArgumentParser(description="Nerves experimental v0.1b help mode") +argsparser.add_argument("-i","--IP",help="IP to bind to (0.0.0.0 by default)", type=str) +argsparser.add_argument("-p","--port",help="Websocket port to bind to (8081 by default)", type=str) +args = argsparser.parse_args() +# Server name +if args.IP: + serverIP = args.IP +else: + serverIP = "0.0.0.0" + +# ORCA destination device +if args.port: + wsPORT = int(args.port) +else: + wsPORT = 8081 + + +def Start(serverIP, wsPORT): + global wserver + + print("Starting WS server ", serverIP, ":", wsPORT) + wserver = WebsocketServer(wsPORT,host=serverIP) + wserver.set_fn_new_client(new_client) + wserver.set_fn_client_left(client_left) + wserver.set_fn_message_received(message_received) + + +def runforever(): + + print("Running WS server...") + leds.mode = 0 + wserver.run_forever() + + +# Called for every WS client connecting (after handshake) +def new_client(client, wserver): + global Players + + + print("New WS client connected and was given id %d" % client['id']) + #sendWSall("/status Hello %d" % client['id']) + #if current == True: + # sendallcurrentccvalues("mmo3") + # sendallcurrentccvalues("ocs2") + + Players+=1 + sendWSall("/status Hello %d" %(client['id'])) + if Players > 1: + #sendWSall("/Players %d" %(Players)) + sendWSall("/players connected:%d" %(Players)) + else: + sendWSall("/players connected:%d" %(Players)) + + + +# Called for every WS client disconnecting +def client_left(client, wserver): + + + try: + print("WS Client(%d) disconnected" % client['id']) + Players-=1 + sendWSall("/players %d" %(Players)) + except: + print("Something weird if coming from",client,"on the wire...") + pass + + +# Called for each WS received message. +def message_received(client, wserver, message): + global crtfunc + + print("") + if len(message) > 200: + message = message[:200]+'..' + + wspath = message.split(" ") + if debug > 0: + print("Main got from WS", client['id'], "said :", message, "splitted in an wspath :", wspath) + else: + print("Main got WS Client", client['id'], "said :", message) + + wscommand = wspath[0].split("/") + + # debug + if debug > 0: + print("wscommand :",wscommand) + + # noarg + if len(wspath) == 1: + args[0] = "noargs" + #print "noargs command" + + # functions : /func 1 + elif wscommand[1] == "func": + if debug > 0: + print("func function with ", wspath[1]) + crtfunc +=1 + if crtfunc == len(funcs): + crtfunc = 0 + print('Launch func', crtfunc) + + sendWSall("/players Function:"+str(crtfunc)) + + # shutdown : /down 1 + elif wscommand[1] == "down": + + if wspath[1] == '1': + import os + print('will shutdown...') + leds.mode = -1 + leds.cls() + sendWSall("/players Stopping...") + os.system("systemctl poweroff") + + + # CC : /device/cc/2 127 + elif wscommand[2] == "cc": + ccvr=int(wscommand[3]) #cc variable + ccvl=int(wspath[1]) #cc value + if debug > 0: + print("ccvr=%d/ccvl=%d"%(ccvr,ccvl)) + if wscommand[1] == "ocs2": + crtvalueOCS2[ccvr]=ccvl + else: + crtvalueMMO3[ccvr]=ccvl + + # Loop back : WS Client -> server -> WS Client + #sendWSall(message) + +# Send through websocket. +# Different websocket library for client (websocket) or server (websocket_server. +# ws object is added here by main.py or client.py startup : midi3.ws = +def send(message): + + if clientmode == True: + send(message) + else: + wserver.send_message_to_all(msg = message) + + + +def sendWSall(message): + + if broadcast == True: + if debug >0: + print("WS sending to all %s" % (message)) + + wserver.send_message_to_all(message) + +# /send all current cc values +def sendallcurrentccvalues(nozoid): + + if broadcast == True: + #print "" + print("sending all current cc values of", nozoid) + + if nozoid == "mmo3": + for ccnumber in range(0,32): + sendWSall("/mmo3/cc/"+str(ccnumber)+" "+str(crtvalueMMO3[ccnumber])) + else: + for ccnumber in range(0,32): + sendWSall("/ocs2/cc/"+str(ccnumber)+" "+str(crtvalueOCS2[ccnumber])) + + +if __name__ == '__main__': + + Start(serverIP, wsPORT) + + try: + + runforever() + + except Exception: + traceback.print_exc() + + + + + + diff --git a/www/config.js b/www/config.js new file mode 100644 index 0000000..ca02a3c --- /dev/null +++ b/www/config.js @@ -0,0 +1 @@ +websocket_uri = "ws://192.168.2.189:8081/" diff --git a/www/css/7f37946c45abf5482c243bf326f82628.eot b/www/css/7f37946c45abf5482c243bf326f82628.eot new file mode 100755 index 0000000..2b3667e Binary files /dev/null and b/www/css/7f37946c45abf5482c243bf326f82628.eot differ diff --git a/www/css/7f37946c45abf5482c243bf326f82628.svg b/www/css/7f37946c45abf5482c243bf326f82628.svg new file mode 100755 index 0000000..c7f2311 --- /dev/null +++ b/www/css/7f37946c45abf5482c243bf326f82628.svg @@ -0,0 +1,828 @@ + + + + +Created by FontForge 20120731 at Sat Jun 6 06:35:01 2020 + By www +This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 License (click below for details). +The font was created by Michal Sulik using Fony, bdfresize, potrace, autotrace and Fontforge. +If you use this font in any public work, please be so nice and leave a link in comments on http://msulik.deviantart.com/. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/css/7f37946c45abf5482c243bf326f82628.ttf b/www/css/7f37946c45abf5482c243bf326f82628.ttf new file mode 100755 index 0000000..0e38d7b Binary files /dev/null and b/www/css/7f37946c45abf5482c243bf326f82628.ttf differ diff --git a/www/css/7f37946c45abf5482c243bf326f82628.woff b/www/css/7f37946c45abf5482c243bf326f82628.woff new file mode 100755 index 0000000..5dc5b8a Binary files /dev/null and b/www/css/7f37946c45abf5482c243bf326f82628.woff differ diff --git a/www/css/7f37946c45abf5482c243bf326f82628.woff2 b/www/css/7f37946c45abf5482c243bf326f82628.woff2 new file mode 100755 index 0000000..bf0e347 Binary files /dev/null and b/www/css/7f37946c45abf5482c243bf326f82628.woff2 differ diff --git a/www/css/LED.eot b/www/css/LED.eot new file mode 100644 index 0000000..423ff5d Binary files /dev/null and b/www/css/LED.eot differ diff --git a/www/css/LED.svg b/www/css/LED.svg new file mode 100644 index 0000000..5266b79 --- /dev/null +++ b/www/css/LED.svg @@ -0,0 +1,519 @@ + + + + +Created by FontForge 20110222 at Mon Mar 7 11:46:57 2011 + By www-data + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/css/LED.ttf b/www/css/LED.ttf new file mode 100644 index 0000000..ab6b07d Binary files /dev/null and b/www/css/LED.ttf differ diff --git a/www/css/LED.woff b/www/css/LED.woff new file mode 100644 index 0000000..f0e1058 Binary files /dev/null and b/www/css/LED.woff differ diff --git a/www/css/common.css b/www/css/common.css new file mode 100644 index 0000000..783c26f --- /dev/null +++ b/www/css/common.css @@ -0,0 +1,377 @@ + .grid-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 0.8fr 47px 0.7fr 2.8fr; + grid-template-areas: ". . ." ". . ." ". . ." ". . ."; + } + .buttons-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 1fr; + grid-template-areas: ". . ." ". . ." ". . ." ". . ."; + } + .buttons-6container { + display: grid; + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . . . ."; + } + .buttons-7container { + display: grid; + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . . . . ."; + } + #title{ + font-family: "Lucida Grande", Verdana, Arial, sans-serif; + text-align: center; + color: #ddd; + font-size: 4ex; + } + #text{ + font-family: "Lucida Grande", Verdana, Arial, sans-serif; + text-align: center; + color: #ccc; + font-size: 2ex; + } + .encoders{ + margin: 0 auto; + } + .mainGrid { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . . . . . ."; + } + .buttonsGrid { + display: grid; + grid-template-columns: 70px 70px 70px 70px 70px 70px 70px 70px 70px 70px 70px 70px; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . . ." ". . . . ." ". . . . ."; + } + .FxGrid { + display: grid; + grid-template-columns: 70px 70px 70px 70px 70px 70px 70px; + grid-template-rows: 1fr; + gap: 1px 1px; + align-items: stretch; + background-color: #020202; + grid-template-areas: ". . . . . . ,"; + } + .RGYGrid { + display: grid; + grid-template-columns: 70px 70px 70px; + grid-template-rows: 1fr; + background-color: #020202; + gap: 1px 1px; + grid-template-areas: ". . ."; + } + .RGBGrid { + display: grid; + grid-template-columns: 70px 70px 70px 70px 70px 70px; + grid-template-rows: 1fr; + gap: 1px 1px; + background-color: #020202; + grid-template-areas: ". . . . . ."; + } + .TopRackGrid { + display: grid; + grid-template-columns: 120px 600px 30px 30px; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . ."; + } + .TextGrid { + display: grid; + grid-template-columns: 250px 370px; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". ."; + } + .Rackgrid { + display: grid; + grid-template-columns: 170px 70px 70px 70px 70px 70px 70px 70px 70px 70px; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . . . . . . . ."; + } + .Settingrid { + display: grid; + grid-template-columns: 110px 80px 80px 100px 80px 80px 140px 40px; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . . . . . . ."; + } + .ColorRackGrid { + display: grid; + grid-template-columns: 170px 70px 70px 70px 70px 70px 70px 70px 70px 70px; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . . . . . . . ."; + } + .grid3 { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . ."; + } + .encodersGrid { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr 1fr 1fr 1fr 1fr; + gap: 1px 1px; + grid-template-areas: "." "." "." "." "."; + } + .webaudiobut{ + border-radius: 4px; + border : #002020 1px solid; + -webkit-box-shadow: 2px 4px 8px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 2px 4px 8px -1px rgba(0,0,0,0.72); + box-shadow: 2px 4px 8px -1px rgba(0,0,0,0.72); + background-image: linear-gradient(174deg, #111,#030303); + } + .content{ + width : 800px; + padding : 10px 20px; + margin : 5px auto; + border-radius: 10px; + border : #212121 2px solid; + background-color: #000000; + background-image: linear-gradient(174deg, #222,#111); + -webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + } + .Rackcontent{ + width : 845px; + border-radius: 3px; + margin : 1px auto; + border : #111 2px solid; + background-color: #111; + -webkit-box-shadow: 4px 6px 44px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 44px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 44px -1px rgba(0,0,0,0.72); + } + .content-title { + color : #ddd; + border : none; + margin-top : 15px; + padding-bottom : 0; + margin-bottom : 0; + background-color : inherit; + } + + .content-names { + padding : 10px; + padding-top : 0; + border : none; + box-shadow : none; + background-color : inherit; + } + .etherled { + color: #666; + font-family: 'Lucida Grande', Verdana, Arial, sans-serif; + font-size: 1.5ex; + text-align: middle; + margin-left: 20px + margin-top: 10px + } + + a { text-decoration: none; + border: none; + outline: none; + } + a:hover, a:focus { + border: none; + outline: none; + color: #fff; + } + + h2 { + position: relative; + line-height: 3ex; + color: #666; + text-align: middle; + font-family: 'Lucida Grande', Verdana, Arial, sans-serif; + font-size: 1.7ex; + margin-top : 1px; + text-shadow: 2px 3px #000; + } + @font-face { + + font-family: "Bus Led Display Small"; + src: url("7f37946c45abf5482c243bf326f82628.eot"); /* IE9*/ + src: url("7f37946c45abf5482c243bf326f82628.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ + url("7f37946c45abf5482c243bf326f82628.woff2") format("woff2"), /* chrome、firefox */ + url("7f37946c45abf5482c243bf326f82628.woff") format("woff"), /* chrome、firefox */ + url("7f37946c45abf5482c243bf326f82628.ttf") format("truetype"), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/ + url("7f37946c45abf5482c243bf326f82628.svg#Bus Led Display Small") format("svg"); /* iOS 4.1- */ + } + + .busled{ + color: #ccc; + background: #000; + font-family:"Bus Led Display Small" !important; + font-size:2em; + font-style:normal; + -webkit-font-smoothing: antialiased; + -webkit-text-stroke-width: 0.7px; + -moz-osx-font-smoothing: grayscale; + } + .navled{ + color: #ccc; + background: #000; + font-family:"Bus Led Display Small" !important; + font-size:1.5em; + margin-left: 2px; + font-style:normal; + -webkit-font-smoothing: antialiased; + -webkit-text-stroke-width: 0.7px; + -moz-osx-font-smoothing: grayscale; + } + .submit { + background: #000; + color: #f0f0f0; + width: 90px; + height: 20px; + text-align: center; + margin-left: 15px; + vertical-align: middle; + font-family:"Bus Led Display Small" !important; + font-size:1.1em; + font-style:normal; + border: 1px solid #555; + -webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + } + .submite { + background: #000; + color: #f0f0f0; + width: 120px; + height: 25px; + text-align: center; + margin-left: 15px; + vertical-align: middle; + font-family:"Bus Led Display Small" !important; + font-size:1.3em; + font-style:normal; + border: 1px solid #033; + -webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + } + .submitalign { + background: #000; + color: #f0f0f0; + width: 60px; + height: 30px; + text-align: center; + margin-left: 15px; + vertical-align: middle; + font-family:"Bus Led Display Small" !important; + font-size:1.4em; + font-style:normal; + border: 1px solid #001515; + -webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + } + .submites { + background: #000; + color: #f0f0f0; + width: 30px; + height: 35px; + text-align: center; + margin-left: 15px; + vertical-align: middle; + font-family:"Bus Led Display Small" !important; + font-size:1.3em; + font-style:normal; + border: 1px solid #445; + -webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + } + .submitext{ + font-family: 'Bus Led Display Small'; + color: #fff; + background: #000; + font-size: 5ex;" + border-radius: 5px; + border : #222222 2px solid; + -webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + + } + #overlay { + position: absolute; + top: 200px; + left: 650px; + -o-transform : scaleX(-1); + -webkit-transform : scaleX(-1); + transform : scaleX(-1); + -ms-filter : fliph; /*IE*/ + filter : fliph; /*IE*/ + } + + #videoel { + -o-transform : scaleX(-1); + -webkit-transform : scaleX(-1); + transform : scaleX(-1); + -ms-filter : fliph; /*IE*/ + filter : fliph; /*IE*/ + } + .lasertext { + font-size: small; + font-family: Helvetica, Verdana, Arial, sans-serif; + color: #bbb; + } + .mgalign { + color: #aaa; + text-align: middle; + font-family: 'Lucida Grande', Verdana, Arial, sans-serif; + display: grid; + height: 400px; + grid-template-columns: 200px 200px 200px 200px; + grid-template-rows: 1Fr; + + border-width: 1px solid #445; + gap: 1px 1px; + grid-template-areas: ". . . . . . . . . ."; + } + .lasergrid { + display: grid; + height: 323px; + width: 200px; + grid-template-columns: 62px 62px 62px; + grid-template-rows: 30px 19px 10px 55px 19px 20px 16px 55px 19px 25px 16px 55px 19px; + line-height: 1; + justify-items: center; + align-items: center; + color:#88c; + } + .lissabox { + display: grid; + height: 353px; + width: 126px; + grid-template-columns: 124px; + grid-template-rows: 15px 338px; + background-color: #000000; + background-image: linear-gradient(147deg, #000000 0%, #434343 374%); + line-height: 1; + padding: 6px; + justify-items: center; + align-items: center; + border-color: #334; + border-style: groove; + border-width: 1px; + } diff --git a/www/css/font-awesome.min.css b/www/css/font-awesome.min.css new file mode 100644 index 0000000..06a13c5 --- /dev/null +++ b/www/css/font-awesome.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.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-adobe:before{content:"\f778"}.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-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:"\f95b"}.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-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:"\f952"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.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-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:"\f905"}.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:"\f907"}.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-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-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:"\f95c"}.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:"\f95d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\f95e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\f95f"}.fa-handshake-slash:before{content:"\f960"}.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:"\f961"}.fa-head-side-cough-slash:before{content:"\f962"}.fa-head-side-mask:before{content:"\f963"}.fa-head-side-virus:before{content:"\f964"}.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-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:"\f965"}.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:"\f913"}.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-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\f955"}.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:"\f966"}.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:"\f967"}.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:"\f91a"}.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:"\f956"}.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-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:"\f968"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.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:"\f91e"}.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:"\f969"}.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:"\f96a"}.fa-pump-soap:before{content:"\f96b"}.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-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:"\f96c"}.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:"\f957"}.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-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:"\f96e"}.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:"\f96f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\f970"}.fa-store-slash:before{content:"\f971"}.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-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:"\f972"}.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:"\f941"}.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-tripadvisor:before{content:"\f262"}.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-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\f949"}.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-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-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-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:"\f974"}.fa-virus-slash:before{content:"\f975"}.fa-viruses:before{content:"\f976"}.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-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-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} \ No newline at end of file diff --git a/www/css/fontawesome.css b/www/css/fontawesome.css new file mode 100644 index 0000000..c73d7c0 --- /dev/null +++ b/www/css/fontawesome.css @@ -0,0 +1,4522 @@ +/*! + * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa, +.fas, +.far, +.fal, +.fad, +.fab { + -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: 0.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: solid 0.08em #eee; + border-radius: .1em; + padding: .2em .25em .15em; } + +.fa-pull-left { + float: left; } + +.fa-pull-right { + float: right; } + +.fa.fa-pull-left, +.fas.fa-pull-left, +.far.fa-pull-left, +.fal.fa-pull-left, +.fab.fa-pull-left { + margin-right: .3em; } + +.fa.fa-pull-right, +.fas.fa-pull-right, +.far.fa-pull-right, +.fal.fa-pull-right, +.fab.fa-pull-right { + margin-left: .3em; } + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; } + +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +.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: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + transform: scale(1, -1); } + +.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); } + +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical, +:root .fa-flip-both { + -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; } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen +readers do not read off random characters that represent icons */ +.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-adobe:before { + content: "\f778"; } + +.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-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: "\f95b"; } + +.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-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: "\f952"; } + +.fa-dashcube:before { + content: "\f210"; } + +.fa-database:before { + content: "\f1c0"; } + +.fa-deaf:before { + content: "\f2a4"; } + +.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-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: "\f905"; } + +.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: "\f907"; } + +.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-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-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: "\f95c"; } + +.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: "\f95d"; } + +.fa-hand-spock:before { + content: "\f259"; } + +.fa-hands:before { + content: "\f4c2"; } + +.fa-hands-helping:before { + content: "\f4c4"; } + +.fa-hands-wash:before { + content: "\f95e"; } + +.fa-handshake:before { + content: "\f2b5"; } + +.fa-handshake-alt-slash:before { + content: "\f95f"; } + +.fa-handshake-slash:before { + content: "\f960"; } + +.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: "\f961"; } + +.fa-head-side-cough-slash:before { + content: "\f962"; } + +.fa-head-side-mask:before { + content: "\f963"; } + +.fa-head-side-virus:before { + content: "\f964"; } + +.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-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: "\f965"; } + +.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: "\f913"; } + +.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-instagram:before { + content: "\f16d"; } + +.fa-instagram-square:before { + content: "\f955"; } + +.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: "\f966"; } + +.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: "\f967"; } + +.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: "\f91a"; } + +.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: "\f956"; } + +.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-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: "\f968"; } + +.fa-people-carry:before { + content: "\f4ce"; } + +.fa-pepper-hot:before { + content: "\f816"; } + +.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: "\f91e"; } + +.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: "\f969"; } + +.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: "\f96a"; } + +.fa-pump-soap:before { + content: "\f96b"; } + +.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-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: "\f96c"; } + +.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: "\f957"; } + +.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-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: "\f96e"; } + +.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: "\f96f"; } + +.fa-store:before { + content: "\f54e"; } + +.fa-store-alt:before { + content: "\f54f"; } + +.fa-store-alt-slash:before { + content: "\f970"; } + +.fa-store-slash:before { + content: "\f971"; } + +.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-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: "\f972"; } + +.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: "\f941"; } + +.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-tripadvisor:before { + content: "\f262"; } + +.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-underline:before { + content: "\f0cd"; } + +.fa-undo:before { + content: "\f0e2"; } + +.fa-undo-alt:before { + content: "\f2ea"; } + +.fa-uniregistry:before { + content: "\f404"; } + +.fa-unity:before { + content: "\f949"; } + +.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-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-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-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: "\f974"; } + +.fa-virus-slash:before { + content: "\f975"; } + +.fa-viruses:before { + content: "\f976"; } + +.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-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-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; } diff --git a/www/css/newstyle.css b/www/css/newstyle.css new file mode 100644 index 0000000..f82c0e1 --- /dev/null +++ b/www/css/newstyle.css @@ -0,0 +1,165 @@ + .grid-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 0.8fr 47px 0.7fr 2.8fr; + grid-template-areas: ". . ." ". . ." ". . ." ". . ."; + } + .buttons-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 1fr; + grid-template-areas: ". . ." ". . ." ". . ." ". . ."; + } + #title{ + font-family: "Lucida Grande", Verdana, Arial, sans-serif; + text-align: center; + color: #ddd; + font-size: 3.3ex; + } + #text{ + font-family: "Lucida Grande", Verdana, Arial, sans-serif; + text-align: center; + color: #ccc; + font-size: 2ex; + } + #smalltext{ + font-family: "Lucida Grande", Verdana, Arial, sans-serif; + text-align: center; + color: #ccc; + font-size: 1.6ex; + } + .encoders{ + margin: 0 auto; + + } + .mainGrid { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . . . . . ."; + } + + .encodersGrid { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr 1fr 1fr 1fr 1fr; + gap: 1px 1px; + grid-template-areas: "." "." "." "." "."; + } + .content{ + width : 880px; + padding : 10px 20px; + margin : 15px auto; + background-color: #000000; + background-image: linear-gradient(174deg, #222,#111); + border-radius: 20px; + border : #0b0b0b 2px solid; + -webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + } + .contentB{ + width : 880px; + padding : 10px 20px; + margin : 15px auto; + background-color: #000000; + background-image: linear-gradient(340deg, #000000 0%, #434343 374%); + border-radius: 20px; + border : #333 1px solid; + } + .content-title { + color : #ddd; + border : none; + margin-top : 15px; + padding-bottom : 0; + margin-bottom : 0; + background-color : inherit; + } + + .content-names { + padding : 10px; + padding-top : 0; + border : none; + box-shadow : none; + background-color : inherit; + } + .TopRackGrid { + display: grid; + grid-template-columns: 120px 600px 80px 80px; + grid-template-rows: 1fr; + gap: 1px 1px; + grid-template-areas: ". . . ."; + } + .webaudiobut{ + border-radius: 5px; + border : #222222 2px solid; + -webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + -moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72); + } + + h2 { + position: relative; + line-height: 3ex; + color: #666; + text-align: middle; + font-family: 'Lucida Grande', Verdana, Arial, sans-serif; + font-size: 1.7ex; + margin-top : 1px; + text-shadow: 2px 3px #000; + } + @font-face { + + font-family: "Bus Led Display Small"; + src: url("7f37946c45abf5482c243bf326f82628.eot"); /* IE9*/ + src: url("7f37946c45abf5482c243bf326f82628.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ + url("7f37946c45abf5482c243bf326f82628.woff2") format("woff2"), /* chrome、firefox */ + url("7f37946c45abf5482c243bf326f82628.woff") format("woff"), /* chrome、firefox */ + url("7f37946c45abf5482c243bf326f82628.ttf") format("truetype"), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/ + url("7f37946c45abf5482c243bf326f82628.svg#Bus Led Display Small") format("svg"); /* iOS 4.1- */ + } + + .busled{ + color: #ddd; + background: #090909; + font-family:"Bus Led Display Small" !important; + font-size:2em;font-style:normal; + -webkit-font-smoothing: antialiased; + -webkit-text-stroke-width: 0.7px; + -moz-osx-font-smoothing: grayscale;} + .info { + background: #000; + width: 200px; + text-align: center; + vertical-align: middle; + height: 30px; + border: 2px solid #445; + font-family: 'Lucida Grande', Verdana, Arial, sans-serif; + color: #aaa; + font-size: 2ex; + } + .shade { + position: relative; + margin: -21px 0 0; + padding: 0; + display: block; + background: #00538F; + width: 100%; + height: 24px; + opacity: 0.25; + text-align: center; + } + .shadow { + -webkit-box-shadow: 4px 6px 14px -1px rgba(0,0,0,0.82); + -moz-box-shadow: 4px 6px 14px -1px rgba(0,0,0,0.82); + box-shadow: 4px 6px 14px -1px rgba(0,0,0,0.82); + } + a:link { + color: #bbb; + } + a:visited { + color: #999; + } + + diff --git a/www/css/style.css b/www/css/style.css new file mode 100755 index 0000000..613dcde --- /dev/null +++ b/www/css/style.css @@ -0,0 +1 @@ +* { box-sizing: border-box; } body {margin: 0;}.row{display:table;padding:10px;width:100%;}.cell{width:8%;display:table-cell;height:75px;}body, html{background-color:#1d1c25;margin:0;padding:0;}.range{-webkit-appearance:none;-moz-appearance:none;position:absolute;left:50%;top:50%;width:200px;margin-top:10px;transform:translate(-50%, -50%);}input[type=range]::-webkit-slider-runnable-track{-webkit-appearance:none;background:linear-gradient(45deg, rgba(59,173,227,1) 0%, rgba(87,111,230,1) 25%, rgba(152,68,183,1) 51%, rgba(255,53,127,1) 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#3bade3 ', endColorstr='#ff357f ', GradientType=1 );height:2px;}input[type=range]:focus{outline:none;}input[type=range]::-moz-range-track{-moz-appearance:none;background:linear-gradient(45deg, rgba(59,173,227,1) 0%, rgba(87,111,230,1) 25%, rgba(152,68,183,1) 51%, rgba(255,53,127,1) 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#3bade3 ', endColorstr='#ff357f ', GradientType=1 );height:2px;}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;border:2px solid;border-radius:50%;height:25px;width:25px;max-width:80px;position:relative;bottom:11px;background-color:#1d1c25;cursor:-webkit-grab;-webkit-transition:border 1000ms ease;transition:border 1000ms ease;}input[type=range]::-moz-range-thumb{-moz-appearance:none;border:2px solid;border-radius:50%;height:25px;width:25px;max-width:80px;position:relative;bottom:11px;background-color:#1d1c25;cursor:-moz-grab;-moz-transition:border 1000ms ease;transition:border 1000ms ease;}.range.blue::-webkit-slider-thumb{border-color:rgb(59,173,227);}.range.ltpurple::-webkit-slider-thumb{border-color:rgb(87,111,230);}.range.purple::-webkit-slider-thumb{border-color:rgb(152,68,183);}.range.pink::-webkit-slider-thumb{border-color:rgb(255,53,127);}.range.blue::-moz-range-thumb{border-color:rgb(59,173,227);}.range.ltpurple::-moz-range-thumb{border-color:rgb(87,111,230);}.range.purple::-moz-range-thumb{border-color:rgb(152,68,183);}.range.pink::-moz-range-thumb{border-color:rgb(255,53,127);}input[type=range]::-webkit-slider-thumb:active{cursor:-webkit-grabbing;}input[type=range]::-moz-range-thumb:active{cursor:-moz-grabbing;}.range.blue{position:relative;background-color:rgba(31,27,27,0.09);width:75%;top:37.5px;}*{box-sizing:border-box;}body{margin:0;}#iy3nk{height:68px;}#il4ah{text-align:center;color:#ef4079;}#i7ox{font-family:Verdana, Geneva, sans-serif;color:#40acef;text-align:left;}#io5q{color:#40acef;}#iy2eh{text-align:center;}#i8a73{text-align:center;color:#4540ef;}#i3fzo{text-align:center;color:#7740ef;}#ikbjg{text-align:center;color:#b140ef;}@media (max-width: 768px){.cell{width:100%;display:block;}} \ No newline at end of file diff --git a/www/css/style2.css b/www/css/style2.css new file mode 100755 index 0000000..115c94b --- /dev/null +++ b/www/css/style2.css @@ -0,0 +1 @@ +input[type=range]::-webkit-slider-runnable-track{-webkit-appearance:none;background:linear-gradient(45deg, rgba(59,173,227,1) 0%, rgba(87,111,230,1) 25%, rgba(152,68,183,1) 51%, rgba(255,53,127,1) 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#3bade3 ', endColorstr='#ff357f ', GradientType=1 );height:2px;}input[type=range]:focus{outline:none;}input[type=range]::-moz-range-track{-moz-appearance:none;background:linear-gradient(45deg, rgba(59,173,227,1) 0%, rgba(87,111,230,1) 25%, rgba(152,68,183,1) 51%, rgba(255,53,127,1) 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#3bade3 ', endColorstr='#ff357f ', GradientType=1 );height:2px;}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;border:2px solid;border-radius:50%;height:25px;width:25px;max-width:80px;position:relative;bottom:11px;background-color:#1d1c25;cursor:-webkit-grab;-webkit-transition:border 1000ms ease;transition:border 1000ms ease;}input[type=range]::-moz-range-thumb{-moz-appearance:none;border:2px solid;border-radius:50%;height:25px;width:25px;max-width:80px;position:relative;bottom:11px;background-color:#1d1c25;cursor:-moz-grab;-moz-transition:border 1000ms ease;transition:border 1000ms ease;}.range.blue::-webkit-slider-thumb{border-color:rgb(59,173,227);}.range.ltpurple::-webkit-slider-thumb{border-color:rgb(87,111,230);}.range.purple::-webkit-slider-thumb{border-color:rgb(152,68,183);}.range.pink::-webkit-slider-thumb{border-color:rgb(255,53,127);}.range.blue::-moz-range-thumb{border-color:rgb(59,173,227);}.range.ltpurple::-moz-range-thumb{border-color:rgb(87,111,230);}.range.purple::-moz-range-thumb{border-color:rgb(152,68,183);}.range.pink::-moz-range-thumb{border-color:rgb(255,53,127);}input[type=range]::-webkit-slider-thumb:active{cursor:-webkit-grabbing;}input[type=range]::-moz-range-thumb:active{cursor:-moz-grabbing;}.range.blue{position:relative;background-color:rgba(31,27,27,0.09);width:75%;top:37.5px;}body{margin:0;}#iy3nk{font-family: "Lucida Grande", Verdana, Arial, sans-serif; font-size: 10ex; height:68px;}#il4ah{text-align:center;color:#ef4079;}#i7ox{font-family:Verdana, Geneva, sans-serif;color:#40acef;text-align:left;}#io5q{color:#40acef;}#iy2eh{text-align:center;}#i8a73{text-align:center;color:#4540ef;}#i3fzo{text-align:center;color:#7740ef;}#ikbjg{text-align:center;color:#b140ef;}@media (max-width: 768px){} \ No newline at end of file diff --git a/www/index.html b/www/index.html new file mode 100644 index 0000000..e33e82d --- /dev/null +++ b/www/index.html @@ -0,0 +1,313 @@ + + + + Nerves + + + + + + + + + + + + + + + + + + + + +
+
+
+

+ Nerves +

+ + +
+
+
+ Nerves +
+
+ 0 Connected +
+
+
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/www/knobs/cls.png b/www/knobs/cls.png new file mode 100644 index 0000000..b92e506 Binary files /dev/null and b/www/knobs/cls.png differ diff --git a/www/knobs/down2.png b/www/knobs/down2.png new file mode 100644 index 0000000..2432cd4 Binary files /dev/null and b/www/knobs/down2.png differ diff --git a/www/knobs/funcs.png b/www/knobs/funcs.png new file mode 100644 index 0000000..2f30b9f Binary files /dev/null and b/www/knobs/funcs.png differ diff --git a/www/knobs/power.png b/www/knobs/power.png new file mode 100644 index 0000000..5c98bb8 Binary files /dev/null and b/www/knobs/power.png differ diff --git a/www/selector.min.css b/www/selector.min.css new file mode 100755 index 0000000..061a532 --- /dev/null +++ b/www/selector.min.css @@ -0,0 +1 @@ +div.selector-element{font-size: 0.75em; display:inline-block;position:relative;width:100%;max-width: 85px;height: 24px;font-family:sans-serif;color: #fbfff5;background-color: #111111}div.selector-element div.selector-selected{display:inline-block;width:100%;height:100%;position:relative;cursor:pointer;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;line-height:30px;padding:0 12px;transition:.15s ease-in-out;border:1px solid gray}div.selector-element div.selector-selected:hover{background-color: #060606}div.selector-element div.selector-selected:after{content:'';position:absolute;top:50%;right:22px;transform:translateY(-50%);height:0;width:0;border-top:5px solid silver;border-left:5px solid transparent;border-right:5px solid transparent}div.selector-element div.selector-selected p.selected-text{display:inline-block;margin:0;width:100%;height:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding-right:30px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}div.selector-element div.selector-options{color: #dbdbdb; display:none;position:absolute;background-color: #111111;top:100%;width:100%;height:auto;max-height:156px;overflow:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid grey;border-top:0;box-shadow:0 2px 3px rgba(0,0,0,0.2);z-index:1;transition:.2s ease-in-out}div.selector-element div.selector-options.options-search{max-height:220px}div.selector-element.open div.selector-options{display:block}div.selector-element div.selector-options div.selector-option{display:block;position:relative;width:100%;height:32px;border-bottom:1px solid silver;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0 12px;line-height:31px;cursor:pointer;overflow:hidden;transition:.15s ease-in-out}div.selector-element div.selector-options div.selector-option.hide{height:0;border-bottom:0;transition:.1s ease-in-out}div.selector-element div.selector-options div.selector-option.option-selected{background-color: #111111}div.selector-element div.selector-options div.selector-option:hover{color: #fbfff5; background-color: #111111}div.selector-element div.selector-options div.selector-option:last-of-type{border-bottom:0}div.selector-element div.selector-options div.selector-option.option-disabled{opacity:.6}div.selector-element div.selector-options div.option-search{display:block;height:32px;line-height:33px;position:relative;width:100%;border-bottom:1px solid grey}div.selector-element div.selector-options div.option-search span{position:absolute;top:50%;transform:translateY(-48%) !important;height:14px;width:14px;cursor:pointer;z-index:1;background:url("../knobs/close.svg") center no-repeat;background-size:11px;right:12px}div.selector-element div.selector-options div.option-search input{display:inline-block;width:100%;height:100%;padding:0 36px 0 36px;font-family:sans-serif;font-size:1em;color: white;outline:0;border:0;background:url("../knobs/search.svg") left 13px center no-repeat;background-size:13px} \ No newline at end of file diff --git a/www/selector.min.js b/www/selector.min.js new file mode 100755 index 0000000..263e77d --- /dev/null +++ b/www/selector.min.js @@ -0,0 +1 @@ +function Selector(a){this.elements={};this.currentElement={};this.currentInstance={};this.config={selector:"select.selector-instance"};this.parameters=a;this.applyParameters();this.core()}Selector.prototype.applyParameters=function(){let allowedParameters=["selector"];for(let i in this.parameters){if(allowedParameters.indexOf(i)===-1){continue}this.config[i]=this.parameters[i]}};Selector.prototype.core=function(){this.getElements();for(let i=0;iMIDI Learn +
  • Learn
  • +
  • Clear
  • +
  • Close
  • +`; + let opt={ + useMidi:0, + midilearn:0, + mididump:0, + outline:0, + knobSrc:null, + knobSprites:0, + knobWidth:0, + knobHeight:0, + knobDiameter:64, + knobColors:"#e00;#000;#000", + sliderSrc:null, + sliderKnobsrc:null, + sliderWidth:0, + sliderHeight:0, + sliderKnobwidth:0, + sliderKnobheight:0, + sliderDitchlength:0, + sliderColors:"#e00;#000;#fcc", + switchWidth:0, + switchHeight:0, + switchDiameter:24, + switchColors:"#e00;#000;#fcc", + paramWidth:32, + paramHeight:16, + paramColors:"#fff;#000", + xypadColors:"#e00;#000;#fcc", + }; + if(window.WebAudioControlsOptions) + Object.assign(opt,window.WebAudioControlsOptions); + class WebAudioControlsWidget extends HTMLElement{ + constructor(){ + super(); + this.addEventListener("keydown",this.keydown); + this.addEventListener("mousedown",this.pointerdown,{passive:false}); + this.addEventListener("touchstart",this.pointerdown,{passive:false}); + this.addEventListener("wheel",this.wheel); + this.addEventListener("mouseover",this.pointerover); + this.addEventListener("mouseout",this.pointerout); + this.addEventListener("contextmenu",this.contextMenu); + this.hover=this.drag=0; + document.body.appendChild(midimenu); + this.basestyle=` +.webaudioctrl-tooltip{ + display:inline-block; + position:absolute; + margin:0 -1000px; + z-index: 999; + background:#eee; + color:#000; + border:1px solid #666; + border-radius:4px; + padding:5px 10px; + text-align:center; + left:0; top:0; + font-size:11px; + opacity:0; + visibility:hidden; +} +.webaudioctrl-tooltip:before{ + content: ""; + position: absolute; + top: 100%; + left: 50%; + margin-left: -8px; + border: 8px solid transparent; + border-top: 8px solid #666; +} +.webaudioctrl-tooltip:after{ + content: ""; + position: absolute; + top: 100%; + left: 50%; + margin-left: -6px; + border: 6px solid transparent; + border-top: 6px solid #eee; +} +`; + } + sendEvent(ev){ + let event; + event=document.createEvent("HTMLEvents"); + event.initEvent(ev,false,true); + this.dispatchEvent(event); + } + getAttr(n,def){ + let v=this.getAttribute(n); + if(v==""||v==null) return def; + switch(typeof(def)){ + case "number": + if(v=="true") return 1; + v=+v; + if(isNaN(v)) return 0; + return v; + } + return v; + } + showtip(d){ + function valstr(x,c,type){ + switch(type){ + case "x": return (x|0).toString(16); + case "X": return (x|0).toString(16).toUpperCase(); + case "d": return (x|0).toString(); + case "f": return x.toFixed(c); + case "s": return x.toString(); + } + return ""; + } + function numformat(s,x){ + if(typeof(x)=="undefined") + return; + let i=s.indexOf("%"); + let c=[0,0],type=0,m=0,r="",j=i+1; + for(;j=0){ + type=s[j]; + break; + } + if(s[j]==".") + m=1; + else + c[m]=c[m]*10+parseInt(s[j]); + } + if(typeof(x)=="number") + r=valstr(x,c[1],type); + else + r=valstr(x.x,c[1],type)+","+valstr(x.y,c[1],type); + if(c[0]>0) + r=(" "+r).slice(-c[0]); + r=s.replace(/%.*[xXdfs]/,r); + return r; + } + let s=this.tooltip; + if(this.drag||this.hover){ + if(this.valuetip){ + if(s==null) + s=`%.${this.digits}f`; + else if(s.indexOf("%")<0) + s+=` : %.${this.digits}f`; + } + if(s){ + this.ttframe.innerHTML=numformat(s,this.convValue); + this.ttframe.style.display="inline-block"; + this.ttframe.style.width="auto"; + this.ttframe.style.height="auto"; + this.ttframe.style.transition="opacity 0.5s "+d+"s,visibility 0.5s "+d+"s"; + this.ttframe.style.opacity=0.9; + this.ttframe.style.visibility="visible"; + let rc=this.getBoundingClientRect(),rc2=this.ttframe.getBoundingClientRect(),rc3=document.documentElement.getBoundingClientRect(); + this.ttframe.style.left=((rc.width-rc2.width)*0.5+1000)+"px"; + this.ttframe.style.top=(-rc2.height-8)+"px"; + return; + } + } + this.ttframe.style.transition="opacity 0.1s "+d+"s,visibility 0.1s "+d+"s"; + this.ttframe.style.opacity=0; + this.ttframe.style.visibility="hidden"; + } + pointerover(e) { + this.hover=1; + this.showtip(0.6); + } + pointerout(e) { + this.hover=0; + this.showtip(0); + } + contextMenu(e){ + if(window.webAudioControlsMidiManager && this.midilearn) + webAudioControlsMidiManager.contextMenuOpen(e,this); + e.preventDefault(); + e.stopPropagation(); + } + setMidiController(channel, cc) { + if (this.listeningToThisMidiController(channel, cc)) return; + this.midiController={ 'channel': channel, 'cc': cc}; + console.log("Added mapping for channel=" + channel + " cc=" + cc + " tooltip=" + this.tooltip); + } + listeningToThisMidiController(channel, cc) { + const c = this.midiController; + if((c.channel === channel || c.channel < 0) && c.cc === cc) + return true; + return false; + } + processMidiEvent(event){ + const channel = event.data[0] & 0xf; + const controlNumber = event.data[1]; + if(this.midiMode == 'learn') { + this.setMidiController(channel, controlNumber); + webAudioControlsMidiManager.contextMenuClose(); + this.midiMode = 'normal'; + } + if(this.listeningToThisMidiController(channel, controlNumber)) { + if(this.tagName=="WEBAUDIO-SWITCH"){ + switch(this.type){ + case "toggle": + if(event.data[2]>=64) + this.setValue(1-this.value,true); + break; + case "kick": + this.setValue(event.data[2]>=64?1:0); + break; + case "radio": + let els=document.querySelectorAll("webaudio-switch[type='radio'][group='"+this.group+"']"); + for(let i=0;i +${this.basestyle} +webaudio-knob{ + display:inline-block; + position:relative; + margin:0; + padding:0; + cursor:pointer; + font-family: sans-serif; + font-size: 11px; +} +.webaudio-knob-body{ + display:inline-block; + position:relative; + margin:0; + padding:0; + vertical-align:bottom; +} + +
    +`; + this.elem=root.childNodes[2]; + this.ttframe=root.childNodes[3]; + this.enable=this.getAttr("enable",1); + this._src=this.getAttr("src",opt.knobSrc); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); + this._value=this.getAttr("value",0); Object.defineProperty(this,"value",{get:()=>{return this._value},set:(v)=>{this._value=v;this.redraw()}}); + this.defvalue=this.getAttr("defvalue",0); + this._min=this.getAttr("min",0); Object.defineProperty(this,"min",{get:()=>{return this._min},set:(v)=>{this._min=+v;this.redraw()}}); + this._max=this.getAttr("max",100); Object.defineProperty(this,"max",{get:()=>{return this._max},set:(v)=>{this._max=+v;this.redraw()}}); + this._step=this.getAttr("step",1); Object.defineProperty(this,"step",{get:()=>{return this._step},set:(v)=>{this._step=+v;this.redraw()}}); + this._sprites=this.getAttr("sprites",opt.knobSprites); Object.defineProperty(this,"sprites",{get:()=>{return this._sprites},set:(v)=>{this._sprites=v;this.setupImage()}}); + this._width=this.getAttr("width",opt.knobWidth); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); + this._height=this.getAttr("height",opt.knobHeight); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); + this._diameter=this.getAttr("diameter",opt.knobDiameter); Object.defineProperty(this,"diameter",{get:()=>{return this._diameter},set:(v)=>{this._diameter=v;this.setupImage()}}); + this._colors=this.getAttr("colors",opt.knobColors); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); + this.outline=this.getAttr("outline",opt.outline); + this.sensitivity=this.getAttr("sensitivity",1); + this.valuetip=this.getAttr("valuetip",1); + this.tooltip=this.getAttr("tooltip",null); + this.conv=this.getAttr("conv",null); + if(this.conv) + this.convValue=eval(this.conv)(this._value); + else + this.convValue=this._value; + this.midilearn=this.getAttr("midilearn",opt.midilearn); + this.midicc=this.getAttr("midicc",null); + + this.midiController={}; + this.midiMode="normal"; + if(this.midicc) { + let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; + let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); + this.setMidiController(ch, cc); + } + this.setupImage(); + this.digits=0; + this.coltab=["#e00","#000","#000"]; + if(window.webAudioControlsMidiManager) +// window.webAudioControlsMidiManager.updateWidgets(); + window.webAudioControlsMidiManager.addWidget(this); + } + disconnectedCallback(){} + setupImage(){ + this.kw=this.width||this.diameter; + this.kh=this.height||this.diameter; + if(!this.src){ + if(this.colors) + this.coltab = this.colors.split(";"); + if(!this.coltab) + this.coltab=["#e00","#000","#000"]; + let svg= +` + + +`; + for(let i=0;i<101;++i){ + svg += ``; + svg += ``; + } + svg += ""; + this.elem.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svg)+")"; +// this.elem.style.backgroundSize = "100% 10100%"; + this.elem.style.backgroundSize = `${this.kw}px ${this.kh*101}px`; + } + else{ + this.elem.style.backgroundImage = "url("+(this.src)+")"; + if(!this.sprites) + this.elem.style.backgroundSize = "100% 100%"; + else{ +// this.elem.style.backgroundSize = `100% ${(this.sprites+1)*100}%`; + this.elem.style.backgroundSize = `${this.kw}px ${this.kh*(this.sprites+1)}px`; + } + } + this.elem.style.outline=this.outline?"":"none"; + this.elem.style.width=this.kw+"px"; + this.elem.style.height=this.kh+"px"; + this.style.height=this.kh+"px"; + this.redraw(); + } + redraw() { + this.digits=0; + if(this.step && this.step < 1) { + for(let n = this.step ; n < 1; n *= 10) + ++this.digits; + } + if(this.valuethis.max){ + this.value=this.max; + return; + } + let range = this.max - this.min; + let style = this.elem.style; + let sp = this.src?this.sprites:100; + if(sp>=1){ + let offset = ((sp * (this.value - this.min) / range) | 0); + style.backgroundPosition = "0px " + (-offset*this.kh) + "px"; + style.transform = 'rotate(0deg)'; + } else { + let deg = 270 * ((this.value - this.min) / range - 0.5); + style.backgroundPosition="0px 0px"; + style.transform = 'rotate(' + deg + 'deg)'; + } + } + _setValue(v){ + if(this.step) + v=(Math.round((v-this.min)/this.step))*this.step+this.min; + this._value=Math.min(this.max,Math.max(this.min,v)); + if(this._value!=this.oldvalue){ + this.oldvalue=this._value; + if(this.conv) + this.convValue=eval(this.conv)(this._value); + else + this.convValue=this._value; + this.redraw(); + this.showtip(0); + return 1; + } + return 0; + } + setValue(v,f){ + if(this._setValue(v) && f) + this.sendEvent("input"),this.sendEvent("change"); + } + wheel(e) { + let delta=(this.max-this.min)*0.01; + delta=e.deltaY>0?-delta:delta; + if(!e.shiftKey) + delta*=5; + if(Math.abs(delta) < this.step) + delta = (delta > 0) ? +this.step : -this.step; + this.setValue(+this.value+delta,true); + e.preventDefault(); + e.stopPropagation(); + } + pointerdown(ev){ + if(!this.enable) + return; + let e=ev; + if(ev.touches){ + e = ev.changedTouches[0]; + this.identifier=e.identifier; + } + else { + if(e.buttons!=1 && e.button!=0) + return; + } + this.elem.focus(); + this.drag=1; + this.showtip(0); + let pointermove=(ev)=>{ + let e=ev; + if(ev.touches){ + for(let i=0;i{ + let e=ev; + if(ev.touches){ + for(let i=0;;){ + if(ev.changedTouches[i].identifier==this.identifier){ + break; + } + if(++i>=ev.changedTouches.length) + return; + } + } + this.drag=0; + this.showtip(0); + this.startPosX = this.startPosY = null; + window.removeEventListener('mousemove', pointermove); + window.removeEventListener('touchmove', pointermove, {passive:false}); + window.removeEventListener('mouseup', pointerup); + window.removeEventListener('touchend', pointerup); + window.removeEventListener('touchcancel', pointerup); + document.body.removeEventListener('touchstart', preventScroll,{passive:false}); + this.sendEvent("change"); + } + let preventScroll=(e)=>{ + e.preventDefault(); + } + if(e.ctrlKey || e.metaKey) + this.setValue(this.defvalue,true); + else { + this.startPosX = e.pageX; + this.startPosY = e.pageY; + this.startVal = this.value; + window.addEventListener('mousemove', pointermove); + window.addEventListener('touchmove', pointermove, {passive:false}); + } + window.addEventListener('mouseup', pointerup); + window.addEventListener('touchend', pointerup); + window.addEventListener('touchcancel', pointerup); + document.body.addEventListener('touchstart', preventScroll,{passive:false}); + ev.preventDefault(); + ev.stopPropagation(); + return false; + } + }); +} catch(error){ + console.log("webaudio-knob already defined"); +} + +try{ + customElements.define("webaudio-slider", class WebAudioSlider extends WebAudioControlsWidget { + constructor(){ + super(); + } + connectedCallback(){ + let root; +// if(this.attachShadow) +// root=this.attachShadow({mode: 'open'}); +// else + root=this; + root.innerHTML= +` +
    +`; + this.elem=root.childNodes[2]; + this.knob=this.elem.childNodes[0]; + this.ttframe=root.childNodes[3]; + this.enable=this.getAttr("enable",1); + this._src=this.getAttr("src",opt.sliderSrc); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); + this._knobsrc=this.getAttr("knobsrc",opt.sliderKnobsrc); Object.defineProperty(this,"knobsrc",{get:()=>{return this._knobsrc},set:(v)=>{this._knobsrc=v;this.setupImage()}}); + this._value=this.getAttr("value",0); Object.defineProperty(this,"value",{get:()=>{return this._value},set:(v)=>{this._value=v;this.redraw()}}); + this.defvalue=this.getAttr("defvalue",0); + this._min=this.getAttr("min",0); Object.defineProperty(this,"min",{get:()=>{return this._min},set:(v)=>{this._min=v;this.redraw()}}); + this._max=this.getAttr("max",100); Object.defineProperty(this,"max",{get:()=>{return this._max},set:(v)=>{this._max=v;this.redraw()}}); + this._step=this.getAttr("step",1); Object.defineProperty(this,"step",{get:()=>{return this._step},set:(v)=>{this._step=v;this.redraw()}}); + this._sprites=this.getAttr("sprites",0); Object.defineProperty(this,"sprites",{get:()=>{return this._sprites},set:(v)=>{this._sprites=v;this.setupImage()}}); + this._direction=this.getAttr("direction",null); Object.defineProperty(this,"direction",{get:()=>{return this._direction},set:(v)=>{this._direction=v;this.setupImage()}}); + this._width=this.getAttr("width",opt.sliderWidth); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); + this._height=this.getAttr("height",opt.sliderHeight); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); + if(this._direction=="horz"){ + if(this._width==0) this._width=128; + if(this._height==0) this._height=24; + } + else{ + if(this._width==0) this._width=24; + if(this._height==0) this._height=128; + } + this._knobwidth=this.getAttr("knobwidth",opt.sliderKnobwidth); Object.defineProperty(this,"knobwidth",{get:()=>{return this._knobwidth},set:(v)=>{this._knobwidth=v;this.setupImage()}}); + this._knobheight=this.getAttr("knbheight",opt.sliderKnobheight); Object.defineProperty(this,"knobheight",{get:()=>{return this._knobheight},set:(v)=>{this._knobheight=v;this.setupImage()}}); + this._ditchlength=this.getAttr("ditchlength",opt.sliderDitchlength); Object.defineProperty(this,"ditchlength",{get:()=>{return this._ditchlength},set:(v)=>{this._ditchlength=v;this.setupImage()}}); + this._colors=this.getAttr("colors",opt.sliderColors); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); + this.outline=this.getAttr("outline",opt.outline); + this.sensitivity=this.getAttr("sensitivity",1); + this.valuetip=this.getAttr("valuetip",1); + this.tooltip=this.getAttr("tooltip",null); + this.conv=this.getAttr("conv",null); + if(this.conv) + this.convValue=eval(this.conv)(this._value); + else + this.convValue=this._value; + this.midilearn=this.getAttr("midilearn",opt.midilearn); + this.midicc=this.getAttr("midicc",null); + this.midiController={}; + this.midiMode="normal"; + if(this.midicc) { + let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; + let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); + this.setMidiController(ch, cc); + } + this.setupImage(); + this.digits=0; + if(window.webAudioControlsMidiManager) +// window.webAudioControlsMidiManager.updateWidgets(); + window.webAudioControlsMidiManager.addWidget(this); + this.elem.onclick=(e)=>{e.stopPropagation()}; + } + disconnectedCallback(){} + setupImage(){ + this.coltab = this.colors.split(";"); + this.dr=this.direction; + this.dlen=this.ditchlength; + if(!this.width){ + if(this.dr=="horz") + this.width=128; + else + this.width=24; + } + if(!this.height){ + if(this.dr=="horz") + this.height=24; + else + this.height=128; + } + if(!this.dr) + this.dr=(this.width<=this.height)?"vert":"horz"; + if(this.dr=="vert"){ + if(!this.dlen) + this.dlen=this.height-this.width; + } + else{ + if(!this.dlen) + this.dlen=this.width-this.height; + } + this.knob.style.backgroundSize = "100% 100%"; + this.elem.style.backgroundSize = "100% 100%"; + this.elem.style.width=this.width+"px"; + this.elem.style.height=this.height+"px"; + this.style.height=this.height+"px"; + this.kwidth=this.knobwidth||(this.dr=="horz"?this.height:this.width); + this.kheight=this.knobheight||(this.dr=="horz"?this.height:this.width); + this.knob.style.width = this.kwidth+"px"; + this.knob.style.height = this.kheight+"px"; + if(!this.src){ + let r=Math.min(this.width,this.height)*0.5; + let svgbody= +` +`; + this.elem.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svgbody)+")"; + } + else{ + this.elem.style.backgroundImage = "url("+(this.src)+")"; + } + if(!this.knobsrc){ + let svgthumb= +` + +`; + this.knob.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svgthumb)+")"; + } + else{ + this.knob.style.backgroundImage = "url("+(this.knobsrc)+")"; + } + this.elem.style.outline=this.outline?"":"none"; + this.redraw(); + } + redraw() { + this.digits=0; + if(this.step && this.step < 1) { + for(let n = this.step ; n < 1; n *= 10) + ++this.digits; + } + if(this.valuethis.max){ + this.value=this.max; + return; + } + let range = this.max - this.min; + let style = this.knob.style; + if(this.dr=="vert"){ + style.left=(this.width-this.kwidth)*0.5+"px"; + style.top=(1-(this.value-this.min)/range)*this.dlen+"px"; + this.sensex=0; this.sensey=1; + } + else{ + style.top=(this.height-this.kheight)*0.5+"px"; + style.left=(this.value-this.min)/range*this.dlen+"px"; + this.sensex=1; this.sensey=0; + } + } + _setValue(v){ + v=(Math.round((v-this.min)/this.step))*this.step+this.min; + this._value=Math.min(this.max,Math.max(this.min,v)); + if(this._value!=this.oldvalue){ + this.oldvalue=this._value; + if(this.conv) + this.convValue=eval(this.conv)(this._value); + else + this.convValue=this._value; + this.redraw(); + this.showtip(0); + return 1; + } + return 0; + } + setValue(v,f){ + if(this._setValue(v)&&f) + this.sendEvent("input"),this.sendEvent("change"); + } + wheel(e) { + let delta=(this.max-this.min)*0.01; + delta=e.deltaY>0?-delta:delta; + if(!e.shiftKey) + delta*=5; + if(Math.abs(delta) < this.step) + delta = (delta > 0) ? +this.step : -this.step; + this.setValue(+this.value+delta,true); + e.preventDefault(); + e.stopPropagation(); + this.redraw(); + } + pointerdown(ev){ + if(!this.enable) + return; + let e=ev; + if(ev.touches){ + e = ev.changedTouches[0]; + this.identifier=e.identifier; + } + else { + if(e.buttons!=1 && e.button!=0) + return; + } + this.elem.focus(); + this.drag=1; + this.showtip(0); + let pointermove=(ev)=>{ + let e=ev; + if(ev.touches){ + for(let i=0;i{ + let e=ev; + if(ev.touches){ + for(let i=0;;){ + if(ev.changedTouches[i].identifier==this.identifier){ + break; + } + if(++i>=ev.changedTouches.length) + return; + } + } + this.drag=0; + this.showtip(0); + this.startPosX = this.startPosY = null; + window.removeEventListener('mousemove', pointermove); + window.removeEventListener('touchmove', pointermove, {passive:false}); + window.removeEventListener('mouseup', pointerup); + window.removeEventListener('touchend', pointerup); + window.removeEventListener('touchcancel', pointerup); + document.body.removeEventListener('touchstart', preventScroll,{passive:false}); + this.sendEvent("change"); + } + let preventScroll=(e)=>{ + e.preventDefault(); + } + if(e.touches) + e = e.touches[0]; + if(e.ctrlKey || e.metaKey) + this.setValue(this.defvalue,true); + else { + this.startPosX = e.pageX; + this.startPosY = e.pageY; + this.startVal = this.value; + window.addEventListener('mousemove', pointermove); + window.addEventListener('touchmove', pointermove, {passive:false}); + } + window.addEventListener('mouseup', pointerup); + window.addEventListener('touchend', pointerup); + window.addEventListener('touchcancel', pointerup); + document.body.addEventListener('touchstart', preventScroll,{passive:false}); + e.preventDefault(); + e.stopPropagation(); + return false; + } + }); +} catch(error){ + console.log("webaudio-slider already defined"); +} + +try{ + customElements.define("webaudio-switch", class WebAudioSwitch extends WebAudioControlsWidget { + constructor(){ + super(); + } + connectedCallback(){ + let root; +// if(this.attachShadow) +// root=this.attachShadow({mode: 'open'}); +// else + root=this; + root.innerHTML= +` +
    +`; + this.elem=root.childNodes[2]; + this.ttframe=this.elem.childNodes[0]; + + this.enable=this.getAttr("enable",1); + this._src=this.getAttr("src",null); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); + this._value=this.getAttr("value",0); Object.defineProperty(this,"value",{get:()=>{return this._value},set:(v)=>{this._value=v;this.redraw()}}); + this.defvalue=this.getAttr("defvalue",0); + this.type=this.getAttr("type","toggle"); + this.group=this.getAttr("group",""); + this._width=this.getAttr("width",0); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); + this._height=this.getAttr("height",0); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); + this._diameter=this.getAttr("diameter",0); Object.defineProperty(this,"diameter",{get:()=>{return this._diameter},set:(v)=>{this._diameter=v;this.setupImage()}}); + this.invert=this.getAttr("invert",0); + this._colors=this.getAttr("colors",opt.switchColors); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); + this.outline=this.getAttr("outline",opt.outline); + this.valuetip=0; + this.tooltip=this.getAttr("tooltip",null); + this.midilearn=this.getAttr("midilearn",opt.midilearn); + this.midicc=this.getAttr("midicc",null); + this.midiController={}; + this.midiMode="normal"; + if(this.midicc) { + let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; + let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); + this.setMidiController(ch, cc); + } + this.setupImage(); + this.digits=0; + if(window.webAudioControlsMidiManager) +// window.webAudioControlsMidiManager.updateWidgets(); + window.webAudioControlsMidiManager.addWidget(this); + this.elem.onclick=(e)=>{e.stopPropagation()}; + } + disconnectedCallback(){} + setupImage(){ + let w=this.width||this.diameter||opt.switchWidth||opt.switchDiameter; + let h=this.height||this.diameter||opt.switchHeight||opt.switchDiameter; + if(!this.src){ + this.coltab = this.colors.split(";"); + let mm=Math.min(w,h); + let svg= +` + + + + +`; + this.elem.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svg)+")"; + this.elem.style.backgroundSize = "100% 200%"; + } + else{ + this.elem.style.backgroundImage = "url("+(this.src)+")"; + if(!this.sprites) + this.elem.style.backgroundSize = "100% 200%"; + else + this.elem.style.backgroundSize = `100% ${(this.sprites+1)*100}%`; + } + this.elem.style.width=w+"px"; + this.elem.style.height=h+"px"; + this.style.height=h+"px"; + this.elem.style.outline=this.outline?"":"none"; + this.redraw(); + } + redraw() { + let style = this.elem.style; + if(this.value^this.invert) + style.backgroundPosition = "0px -100%"; + else + style.backgroundPosition = "0px 0px"; + } + setValue(v,f){ + this.value=v; + this.checked=(!!v); + if(this.value!=this.oldvalue){ + this.redraw(); + this.showtip(0); + if(f){ + this.sendEvent("input"); + this.sendEvent("change"); + } + this.oldvalue=this.value; + } + } + pointerdown(ev){ + if(!this.enable) + return; + let e=ev; + if(ev.touches){ + e = ev.changedTouches[0]; + this.identifier=e.identifier; + } + else { + if(e.buttons!=1 && e.button!=0) + return; + } + this.elem.focus(); + this.drag=1; + this.showtip(0); + let pointermove=(e)=>{ + e.preventDefault(); + e.stopPropagation(); + return false; + } + let pointerup=(e)=>{ + this.drag=0; + this.showtip(0); + window.removeEventListener('mousemove', pointermove); + window.removeEventListener('touchmove', pointermove, {passive:false}); + window.removeEventListener('mouseup', pointerup); + window.removeEventListener('touchend', pointerup); + window.removeEventListener('touchcancel', pointerup); + document.body.removeEventListener('touchstart', preventScroll,{passive:false}); + if(this.type=="kick"){ + this.value=0; + this.checked=false; + this.redraw(); + this.sendEvent("change"); + } + this.sendEvent("click"); + e.preventDefault(); + e.stopPropagation(); + } + let preventScroll=(e)=>{ + e.preventDefault(); + } + switch(this.type){ + case "kick": + this.setValue(1); + this.sendEvent("change"); + break; + case "toggle": + if(e.ctrlKey || e.metaKey) + this.value=defvalue; + else + this.value=1-this.value; + this.checked=!!this.value; + this.sendEvent("change"); + break; + case "radio": + let els=document.querySelectorAll("webaudio-switch[type='radio'][group='"+this.group+"']"); + for(let i=0;i +${this.basestyle} +webaudio-param{ + display:inline-block; + user-select:none; + margin:0; + padding:0; + font-family: sans-serif; + font-size: 8px; + cursor:pointer; + position:relative; + vertical-align:baseline; +} +.webaudio-param-body{ + display:inline-block; + position:relative; + text-align:center; + border:1px solid #888; + background:none; + border-radius:4px; + margin:0; + padding:0; + font-family:sans-serif; + font-size:11px; + vertical-align:bottom; +} + +
    +`; + this.elem=root.childNodes[2]; + this.ttframe=root.childNodes[3]; + this.enable=this.getAttr("enable",1); + this._value=this.getAttr("value",0); Object.defineProperty(this,"value",{get:()=>{return this._value},set:(v)=>{this._value=v;this.redraw()}}); + this.defvalue=this.getAttr("defvalue",0); + this._fontsize=this.getAttr("fontsize",9); Object.defineProperty(this,"fontsize",{get:()=>{return this._fontsize},set:(v)=>{this._fontsize=v;this.setupImage()}}); + this._src=this.getAttr("src",null); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); + this.link=this.getAttr("link",""); + this._width=this.getAttr("width",32); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); + this._height=this.getAttr("height",20); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); + this._colors=this.getAttr("colors","#fff;#000"); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); + this.outline=this.getAttr("outline",opt.outline); + this.midiController={}; + this.midiMode="normal"; + if(this.midicc) { + let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; + let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); + this.setMidiController(ch, cc); + } + this.setupImage(); + if(window.webAudioControlsMidiManager) +// window.webAudioControlsMidiManager.updateWidgets(); + window.webAudioControlsMidiManager.addWidget(this); + this.fromLink=((e)=>{ + this.setValue(e.target.convValue.toFixed(e.target.digits)); + }).bind(this); + this.elem.onchange=()=>{ + this.value=this.elem.value; + let le=document.getElementById(this.link); + if(le) + le.setValue(+this.elem.value); + } + } + disconnectedCallback(){} + setupImage(){ + this.coltab = this.colors.split(";"); + this.elem.style.color=this.coltab[0]; + if(!this.src){ + this.elem.style.backgroundColor=this.coltab[1]; + } + else{ + this.elem.style.backgroundImage = "url("+(this.src)+")"; + this.elem.style.backgroundSize = "100% 100%"; + } + this.elem.style.width=this.width+"px"; + this.elem.style.height=this.height+"px"; + this.elem.style.fontSize=this.fontsize+"px"; + this.elem.style.outline=this.outline?"":"none"; + let l=document.getElementById(this.link); + if(l&&typeof(l.value)!="undefined"){ + this.setValue(l.value.toFixed(l.digits)); + l.addEventListener("input",(e)=>{this.setValue(l.value.toFixed(l.digits))}); + } + this.redraw(); + } + redraw() { + this.elem.value=this.value; + } + setValue(v,f){ + this.value=v; + if(this.value!=this.oldvalue){ + this.redraw(); + this.showtip(0); + if(f){ + let event=document.createEvent("HTMLEvents"); + event.initEvent("change",false,true); + this.dispatchEvent(event); + } + this.oldvalue=this.value; + } + } + pointerdown(ev){ + if(!this.enable) + return; + let e=ev; + if(ev.touches) + e = ev.touches[0]; + else { + if(e.buttons!=1 && e.button!=0) + return; + } + this.elem.focus(); + this.redraw(); + } + }); +} catch(error){ + console.log("webaudio-param already defined"); +} + +try{ + customElements.define("webaudio-keyboard", class WebAudioKeyboard extends WebAudioControlsWidget { + constructor(){ + super(); + } + connectedCallback(){ + let root; +// if(this.attachShadow) +// root=this.attachShadow({mode: 'open'}); +// else + root=this; + root.innerHTML= +` +
    +`; + this.cv=root.childNodes[2]; + this.ttframe=root.childNodes[3]; + this.ctx=this.cv.getContext("2d"); + this._values=[]; + this.enable=this.getAttr("enable",1); + this._width=this.getAttr("width",480); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); + this._height=this.getAttr("height",128); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); + this._min=this.getAttr("min",0); Object.defineProperty(this,"min",{get:()=>{return this._min},set:(v)=>{this._min=+v;this.redraw()}}); + this._keys=this.getAttr("keys",25); Object.defineProperty(this,"keys",{get:()=>{return this._keys},set:(v)=>{this._keys=+v;this.setupImage()}}); + this._colors=this.getAttr("colors","#222;#eee;#ccc;#333;#000;#e88;#c44;#c33;#800"); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); + this.outline=this.getAttr("outline",opt.outline); + this.midilearn=this.getAttr("midilearn",0); + this.midicc=this.getAttr("midicc",null); + this.press=0; + this.keycodes1=[90,83,88,68,67,86,71,66,72,78,74,77,188,76,190,187,191,226]; + this.keycodes2=[81,50,87,51,69,82,53,84,54,89,55,85,73,57,79,48,80,192,222,219]; + this.addEventListener("keyup",this.keyup); + this.midiController={}; + this.midiMode="normal"; + if(this.midicc) { + let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; + let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); + this.setMidiController(ch, cc); + } + this.setupImage(); + this.digits=0; + if(window.webAudioControlsMidiManager) + window.webAudioControlsMidiManager.addWidget(this); + } + disconnectedCallback(){} + setupImage(){ + this.cv.style.width=this.width+"px"; + this.cv.style.height=this.height+"px"; + this.bheight = this.height * 0.55; + this.kp=[0,7/12,1,3*7/12,2,3,6*7/12,4,8*7/12,5,10*7/12,6]; + this.kf=[0,1,0,1,0,0,1,0,1,0,1,0]; + this.ko=[0,0,(7*2)/12-1,0,(7*4)/12-2,(7*5)/12-3,0,(7*7)/12-4,0,(7*9)/12-5,0,(7*11)/12-6]; + this.kn=[0,2,4,5,7,9,11]; + this.coltab=this.colors.split(";"); + this.cv.width = this.width; + this.cv.height = this.height; + this.cv.style.width = this.width+'px'; + this.cv.style.height = this.height+'px'; + this.style.height = this.height+'px'; + this.cv.style.outline=this.outline?"":"none"; + this.bheight = this.height * 0.55; + this.max=this.min+this.keys-1; + this.dispvalues=[]; + this.valuesold=[]; + if(this.kf[this.min%12]) + --this.min; + if(this.kf[this.max%12]) + ++this.max; + this.redraw(); + } + redraw(){ + function rrect(ctx, x, y, w, h, r, c1, c2) { + if(c2) { + let g=ctx.createLinearGradient(x,y,x+w,y); + g.addColorStop(0,c1); + g.addColorStop(1,c2); + ctx.fillStyle=g; + } + else + ctx.fillStyle=c1; + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineTo(x+w, y); + ctx.lineTo(x+w, y+h-r); + ctx.quadraticCurveTo(x+w, y+h, x+w-r, y+h); + ctx.lineTo(x+r, y+h); + ctx.quadraticCurveTo(x, y+h, x, y+h-r); + ctx.lineTo(x, y); + ctx.fill(); + } + this.ctx.fillStyle = this.coltab[0]; + this.ctx.fillRect(0,0,this.width,this.height); + let x0=7*((this.min/12)|0)+this.kp[this.min%12]; + let x1=7*((this.max/12)|0)+this.kp[this.max%12]; + let n=x1-x0; + this.wwidth=(this.width-1)/(n+1); + this.bwidth=this.wwidth*7/12; + let h2=this.bheight; + let r=Math.min(8,this.wwidth*0.2); + for(let i=this.min,j=0;i<=this.max;++i) { + if(this.kf[i%12]==0) { + let x=this.wwidth*(j++)+1; + if(this.dispvalues.indexOf(i)>=0) + rrect(this.ctx,x,1,this.wwidth-1,this.height-2,r,this.coltab[5],this.coltab[6]); + else + rrect(this.ctx,x,1,this.wwidth-1,this.height-2,r,this.coltab[1],this.coltab[2]); + } + } + r=Math.min(8,this.bwidth*0.3); + for(let i=this.min;i=0) + rrect(this.ctx,x,1,this.bwidth,h2,r,this.coltab[7],this.coltab[8]); + else + rrect(this.ctx,x,1,this.bwidth,h2,r,this.coltab[3],this.coltab[4]); + this.ctx.strokeStyle=this.coltab[0]; + this.ctx.stroke(); + } + } + } + _setValue(v){ + if(this.step) + v=(Math.round((v-this.min)/this.step))*this.step+this.min; + this._value=Math.min(this.max,Math.max(this.min,v)); + if(this._value!=this.oldvalue){ + this.oldvalue=this._value; + this.redraw(); + this.showtip(0); + return 1; + } + return 0; + } + setValue(v,f){ + if(this._setValue(v) && f) + this.sendEvent("input"),this.sendEvent("change"); + } + wheel(e){} + keydown(e){ + let m=Math.floor((this.min+11)/12)*12; + let k=this.keycodes1.indexOf(e.keyCode); + if(k<0) { + k=this.keycodes2.indexOf(e.keyCode); + if(k>=0) k+=12; + } + if(k>=0){ + k+=m; + if(this.currentKey!=k){ + this.currentKey=k; + this.sendEventFromKey(1,k); + this.setNote(1,k); + } + } + } + keyup(e){ + let m=Math.floor((this.min+11)/12)*12; + let k=this.keycodes1.indexOf(e.keyCode); + if(k<0) { + k=this.keycodes2.indexOf(e.keyCode); + if(k>=0) k+=12; + } + if(k>=0){ + k+=m; + this.currentKey=-1; + this.sendEventFromKey(0,k); + this.setNote(0,k); + } + } + pointerdown(ev){ + this.cv.focus(); + if(this.enable) { + ++this.press; + } + let pointermove=(ev)=>{ + if(!this.enable) + return; + let r=this.getBoundingClientRect(); + let v=[],p; + if(ev.touches) + p=ev.targetTouches; + else if(this.press) + p=[ev]; + else + p=[]; + if(p.length>0) + this.drag=1; + for(let i=0;i=0&&py=this.min&&k<=this.max) + v.push(k); + } + } + v.sort(); + this.values=v; + this.sendevent(); + this.redraw(); + } + + let pointerup=(ev)=>{ + if(this.enable) { + if(ev.touches) + this.press=ev.touches.length; + else + this.press=0; + pointermove(ev); + this.sendevent(); + if(this.press==0){ + window.removeEventListener('mousemove', pointermove); + window.removeEventListener('touchmove', pointermove, {passive:false}); + window.removeEventListener('mouseup', pointerup); + window.removeEventListener('touchend', pointerup); + window.removeEventListener('touchcancel', pointerup); + document.body.removeEventListener('touchstart', preventScroll,{passive:false}); + } + this.redraw(); + } + this.drag=0; + ev.preventDefault(); + } + let preventScroll=(ev)=>{ + ev.preventDefault(); + } + window.addEventListener('mousemove', pointermove); + window.addEventListener('touchmove', pointermove, {passive:false}); + window.addEventListener('mouseup', pointerup); + window.addEventListener('touchend', pointerup); + window.addEventListener('touchcancel', pointerup); + document.body.addEventListener('touchstart', preventScroll,{passive:false}); + pointermove(ev); + ev.preventDefault(); + ev.stopPropagation(); + } + sendEventFromKey(s,k){ + let ev=document.createEvent('HTMLEvents'); + ev.initEvent('change',true,true); + ev.note=[s,k]; + this.dispatchEvent(ev); + } + sendevent(){ + let notes=[]; + for(let i=0,j=this.valuesold.length;i=0) this.dispvalues.splice(n,1); + } + } + setNote(state,note) { + this.setdispvalues(state,note); + this.redraw(); + } + }); +} catch(error){ + console.log("webaudio-keyboard already defined"); +} + +try{ + customElements.define("webaudio-xypad", class WebAudioXYPad extends WebAudioControlsWidget { + constructor(){ + super(); + } + connectedCallback(){ + let root; +// if(this.attachShadow) +// root=this.attachShadow({mode: 'open'}); +// else + root=this; + root.innerHTML= +` +
    +`; + this.elem=root.childNodes[2]; + this.knob=this.elem.childNodes[0]; + this.ttframe=root.childNodes[3]; + + this.enable=this.getAttr("enable",1); + this._src=this.getAttr("src",opt.sliderSrc); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); + this._knobsrc=this.getAttr("knobsrc",opt.sliderKnobsrc); Object.defineProperty(this,"knobsrc",{get:()=>{return this._knobsrc},set:(v)=>{this._knobsrc=v;this.setupImage()}}); + this._x=this.getAttr("x",50); Object.defineProperty(this,"x",{get:()=>{return this._x},set:(v)=>{this._x=v;this.redraw()}}); + this._y=this.getAttr("y",50); Object.defineProperty(this,"y",{get:()=>{return this._y},set:(v)=>{this._y=v;this.redraw()}}); + this.defx=this.getAttr("defx",50); + this.defy=this.getAttr("defy",50); + this._min=this.getAttr("min",0); Object.defineProperty(this,"min",{get:()=>{return this._min},set:(v)=>{this._min=v;this.redraw()}}); + this._max=this.getAttr("max",100); Object.defineProperty(this,"max",{get:()=>{return this._max},set:(v)=>{this._max=v;this.redraw()}}); + this._step=this.getAttr("step",1); Object.defineProperty(this,"step",{get:()=>{return this._step},set:(v)=>{this._step=v;this.redraw()}}); + this._sprites=this.getAttr("sprites",0); Object.defineProperty(this,"sprites",{get:()=>{return this._sprites},set:(v)=>{this._sprites=v;this.setupImage()}}); + this._width=this.getAttr("width",128); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); + this._height=this.getAttr("height",128); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); + this._knobwidth=this.getAttr("knobwidth",28); Object.defineProperty(this,"knobwidth",{get:()=>{return this._knobwidth},set:(v)=>{this._knobwidth=v;this.setupImage()}}); + this._knobheight=this.getAttr("knbheight",28); Object.defineProperty(this,"knobheight",{get:()=>{return this._knobheight},set:(v)=>{this._knobheight=v;this.setupImage()}}); + this._colors=this.getAttr("colors",opt.sliderColors); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); + this.outline=this.getAttr("outline",opt.outline); + this.valuetip=this.getAttr("valuetip",1); + this.tooltip=this.getAttr("tooltip",null); + this.conv=this.getAttr("conv",null); + if(this.conv){ + this.convValue={x:eval(this.conv)(this._x),y:eval(this.conv)(this._y)}; + } + else + this.convValue={x:this._x,y:this._y}; + this.midilearn=this.getAttr("midilearn",opt.midilearn); + this.midicc=this.getAttr("midicc",null); + this.midiController={}; + this.midiMode="normal"; + if(this.midicc) { + let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; + let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); + this.setMidiController(ch, cc); + } + this.setupImage(); + this.digits=0; + if(window.webAudioControlsMidiManager) +// window.webAudioControlsMidiManager.updateWidgets(); + window.webAudioControlsMidiManager.addWidget(this); + this.elem.onclick=(e)=>{e.stopPropagation()}; + } + disconnectedCallback(){} + setupImage(){ + this.coltab = this.colors.split(";"); + this.dr=this.direction; + this.dlen=this.ditchlength; + if(!this.width) + this.width=256; + if(!this.height) + this.height=256; + this.knob.style.backgroundSize = "100% 100%"; + this.elem.style.backgroundSize = "100% 100%"; + this.elem.style.width=this.width+"px"; + this.elem.style.height=this.height+"px"; + this.kwidth=this.knobwidth||(this.width*0.15|0); + this.kheight=this.knobheight||(this.height*0.15|0); + this.knob.style.width = this.kwidth+"px"; + this.knob.style.height = this.kheight+"px"; + if(!this.src){ + let r=Math.min(this.width,this.height)*0.02; + let svgbody= +` +`; + this.elem.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svgbody)+")"; + } + else{ + this.elem.style.backgroundImage = "url("+(this.src)+")"; + } + if(!this.knobsrc){ + let svgthumb= +` + +`; + this.knob.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svgthumb)+")"; + } + else{ + this.knob.style.backgroundImage = "url("+(this.knobsrc)+")"; + } + this.elem.style.outline=this.outline?"":"none"; + this.redraw(); + } + redraw() { + this.digits=0; + if(this.step && this.step < 1) { + for(let n = this.step ; n < 1; n *= 10) + ++this.digits; + } + if(this.valuethis.max){ + this.value=this.max; + return; + } + let range = this.max - this.min; + let style = this.knob.style; + style.left=(this.width-this.kwidth)*(this._x-this.min)/(this.max-this.min)+"px"; style.top=(this.height-this.kheight)*(1-(this._y-this.min)/(this.max-this.min))+"px"; + this.sensex=0; this.sensey=1; + } + _setX(v){ + v=(Math.round((v-this.min)/this.step))*this.step+this.min; + this._x=Math.min(this.max,Math.max(this.min,v)); + if(this._x!=this.oldx){ + this.oldx=this._x; + if(this.conv){ + this.convValue={x:eval(this.conv)(this._x),y:eval(this.conv)(this._y)}; + } + else + this.convValue={x:this._x,y:this._y}; + this.redraw(); + this.showtip(0); + return 1; + } + return 0; + } + _setY(v){ + v=(Math.round((v-this.min)/this.step))*this.step+this.min; + this._y=Math.min(this.max,Math.max(this.min,v)); + if(this._y!=this.oldy){ + this.oldy=this._y; + if(this.conv){ + this.convValue={x:eval(this.conv)(this._x),y:eval(this.conv)(this._y)}; + } + else + this.convValue={x:this._x,y:this._y}; + this.redraw(); + this.showtip(0); + return 1; + } + return 0; + } + setX(v,f){ + if(this._setX(v)&&f) + this.sendEvent("input"),this.sendEvent("change"); + } + setY(v,f){ + if(this._setY(v)&&f) + this.sendEvent("input"),this.sendEvent("change"); + } + wheel(e) { + let delta=(this.max-this.min)*0.01; + delta=e.deltaY>0?-delta:delta; + if(!e.shiftKey) + delta*=5; + if(Math.abs(delta) < this.step) + delta = (delta > 0) ? +this.step : -this.step; + this.setValue(+this.value+delta,true); + e.preventDefault(); + e.stopPropagation(); + this.redraw(); + } + pointerdown(ev){ + if(!this.enable) + return; + let e=ev; + if(ev.touches){ + e = ev.changedTouches[0]; + this.identifier=e.identifier; + } + else { + if(e.buttons!=1 && e.button!=0) + return; + } + this.elem.focus(); + this.drag=1; + this.showtip(0); + let pointermove=(ev)=>{ + let e=ev; + if(ev.touches){ + for(let i=0;i{ + let e=ev; + if(ev.touches){ + for(let i=0;;){ + if(ev.changedTouches[i].identifier==this.identifier){ + break; + } + if(++i>=ev.changedTouches.length) + return; + } + } + this.drag=0; + this.showtip(0); + this.startPosX = this.startPosY = null; + window.removeEventListener('mousemove', pointermove); + window.removeEventListener('touchmove', pointermove, {passive:false}); + window.removeEventListener('mouseup', pointerup); + window.removeEventListener('touchend', pointerup); + window.removeEventListener('touchcancel', pointerup); + document.body.removeEventListener('touchstart', preventScroll,{passive:false}); + this.sendEvent("change"); + } + pointermove(ev); + let preventScroll=(e)=>{ + e.preventDefault(); + } + if(e.touches) + e = e.touches[0]; + if(e.ctrlKey || e.metaKey) + this.setValue(this.defvalue,true); + else { + this.startPosX = e.pageX; + this.startPosY = e.pageY; + this.startVal = this.value; + window.addEventListener('mousemove', pointermove); + window.addEventListener('touchmove', pointermove, {passive:false}); + } + window.addEventListener('mouseup', pointerup); + window.addEventListener('touchend', pointerup); + window.addEventListener('touchcancel', pointerup); + document.body.addEventListener('touchstart', preventScroll,{passive:false}); + e.preventDefault(); + e.stopPropagation(); + return false; + } + }); +} catch(error){ + console.log("webaudio-xypad already defined"); +} + + + + // FOR MIDI LEARN + class WebAudioControlsMidiManager { + constructor(){ + this.midiAccess = null; + this.listOfWidgets = []; + this.listOfExternalMidiListeners = []; + this.updateWidgets(); + this.initWebAudioControls(); + } + addWidget(w){ + this.listOfWidgets.push(w); + } + updateWidgets(){ +// this.listOfWidgets = document.querySelectorAll("webaudio-knob,webaudio-slider,webaudio-switch"); + } + initWebAudioControls() { + if(navigator.requestMIDIAccess) { + navigator.requestMIDIAccess().then( + (ma)=>{this.midiAccess = ma,this.enableInputs()}, + (err)=>{ console.log("MIDI not initialized - error encountered:" + err.code)} + ); + } + } + enableInputs() { + let inputs = this.midiAccess.inputs.values(); + console.log("Found " + this.midiAccess.inputs.size + " MIDI input(s)"); + for(let input = inputs.next(); input && !input.done; input = inputs.next()) { + console.log("Connected input: " + input.value.name); + input.value.onmidimessage = this.handleMIDIMessage.bind(this); + } + } + midiConnectionStateChange(e) { + console.log("connection: " + e.port.name + " " + e.port.connection + " " + e.port.state); + enableInputs(); + } + + onMIDIStarted(midi) { + this.midiAccess = midi; + midi.onstatechange = this.midiConnectionStateChange; + enableInputs(midi); + } + // Add hooks for external midi listeners support + addMidiListener(callback) { + this.listOfExternalMidiListeners.push(callback); + } + getCurrentConfigAsJSON() { + return currentConfig.stringify(); + } + handleMIDIMessage(event) { + this.listOfExternalMidiListeners.forEach(function (externalListener) { + externalListener(event); + }); + if(((event.data[0] & 0xf0) == 0xf0) || ((event.data[0] & 0xf0) == 0xb0 && event.data[1] >= 120)) + return; + for(let w of this.listOfWidgets) { + if(w.processMidiEvent) + w.processMidiEvent(event); + } + if(opt.mididump) + console.log(event.data); + } + contextMenuOpen(e,knob){ + if(!this.midiAccess) + return; + let menu=document.getElementById("webaudioctrl-context-menu"); + menu.style.left=e.pageX+"px"; + menu.style.top=e.pageY+"px"; + menu.knob=knob; + menu.classList.add("active"); + menu.knob.focus(); +// document.activeElement.onblur=this.contextMenuClose; + menu.knob.addEventListener("keydown",this.contextMenuCloseByKey.bind(this)); + } + contextMenuCloseByKey(e){ + if(e.keyCode==27) + this.contextMenuClose(); + } + contextMenuClose(){ + let menu=document.getElementById("webaudioctrl-context-menu"); + menu.knob.removeEventListener("keydown",this.contextMenuCloseByKey); + menu.classList.remove("active"); + let menuItemLearn=document.getElementById("webaudioctrl-context-menu-learn"); + menuItemLearn.innerHTML = 'Learn'; + menu.knob.midiMode = 'normal'; + } + contextMenuLearn(){ + let menu=document.getElementById("webaudioctrl-context-menu"); + let menuItemLearn=document.getElementById("webaudioctrl-context-menu-learn"); + menuItemLearn.innerHTML = 'Listening...'; + menu.knob.midiMode = 'learn'; + } + contextMenuClear(e){ + let menu=document.getElementById("webaudioctrl-context-menu"); + menu.knob.midiController={}; + this.contextMenuClose(); + } + } + if(window.UseWebAudioControlsMidi||opt.useMidi) + window.webAudioControlsMidiManager = new WebAudioControlsMidiManager(); +} diff --git a/www/webcomponents-lite.js b/www/webcomponents-lite.js new file mode 100755 index 0000000..d3e7beb --- /dev/null +++ b/www/webcomponents-lite.js @@ -0,0 +1,197 @@ +(function(){/* + + Copyright (c) 2016 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ +'use strict';var p,q="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this,ba="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)};function ca(){ca=function(){};q.Symbol||(q.Symbol=da)}var da=function(){var a=0;return function(b){return"jscomp_symbol_"+(b||"")+a++}}(); +function ea(){ca();var a=q.Symbol.iterator;a||(a=q.Symbol.iterator=q.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&ba(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return fa(this)}});ea=function(){}}function fa(a){var b=0;return ha(function(){return b"+this.innerHTML+""},set:function(a){if(this.parentNode){J.body.innerHTML=a;for(a=this.ownerDocument.createDocumentFragment();J.body.firstChild;)l.call(a, +J.body.firstChild);m.call(this.parentNode,a,this)}else throw Error("Failed to set the 'outerHTML' property on 'Element': This element has no parent node.");},configurable:!0})};na(a.prototype);aa(a.prototype);a.J=function(c){c=b(c,"template");for(var d=0,e=c.length,f;d]/g, +U=function(a){switch(a){case "&":return"&";case "<":return"<";case ">":return">";case "\u00a0":return" "}}}if(c||eb){a.ca=function(a,b){var c=f.call(a,!1);this.D&&this.D(c);b&&(l.call(c.content,f.call(a.content,!0)),fb(c.content,a.content));return c};var fb=function(c,d){if(d.querySelectorAll&&(d=b(d,"template"),0!==d.length)){c=b(c,"template");for(var e=0,f=c.length,h,g;e]*)(rel=['|"]?stylesheet['|"]?[^>]*>)/g,x={La:function(a,b){a.href&&a.setAttribute("href",x.Y(a.getAttribute("href"),b));a.src&&a.setAttribute("src",x.Y(a.getAttribute("src"),b));if("style"===a.localName){var c=x.ta(a.textContent,b,Ca);a.textContent=x.ta(c,b,Da)}},ta:function(a,b,c){return a.replace(c, +function(a,c,d,e){a=d.replace(/["']/g,"");b&&(a=x.Y(a,b));return c+"'"+a+"'"+e})},Y:function(a,b){if(void 0===x.ba){x.ba=!1;try{var c=new URL("b","http://a");c.pathname="c%20d";x.ba="http://a/c%20d"===c.href}catch(Lg){}}if(x.ba)return(new URL(a,b)).href;c=x.Ba;c||(c=document.implementation.createHTMLDocument("temp"),x.Ba=c,c.ma=c.createElement("base"),c.head.appendChild(c.ma),c.la=c.createElement("a"));c.ma.href=b;c.la.href=a;return c.la.href||a}},na={async:!0,load:function(a,b,c){if(a)if(a.match(/^data:/)){a= +a.split(",");var d=a[1];d=-1e.status?b(d,a):c(d)};e.send()}else c("error: href must be specified")}},aa=/Trident/.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent); +k.prototype.loadImports=function(a){var b=this;a=m(a,"link[rel=import]");n(a,function(a){return b.s(a)})};k.prototype.s=function(a){var b=this,c=a.href;if(void 0!==this.a[c]){var d=this.a[c];d&&d.__loaded&&(a.__import=d,this.h(a))}else this.b++,this.a[c]="pending",na.load(c,function(a,d){a=b.Sa(a,d||c);b.a[c]=a;b.b--;b.loadImports(a);b.L()},function(){b.a[c]=null;b.b--;b.L()})};k.prototype.Sa=function(a,b){if(!a)return document.createDocumentFragment();aa&&(a=a.replace(Ea,function(a,b,c){return-1=== +a.indexOf("type=")?b+" type=import-disable "+c:a}));var c=document.createElement("template");c.innerHTML=a;if(c.content)a=c.content,l(a);else for(a=document.createDocumentFragment();c.firstChild;)a.appendChild(c.firstChild);if(c=a.querySelector("base"))b=x.Y(c.getAttribute("href"),b),c.removeAttribute("href");c=m(a,'link[rel=import],link[rel=stylesheet][href][type=import-disable],style:not([type]),link[rel=stylesheet][href]:not([type]),script:not([type]),script[type="application/javascript"],script[type="text/javascript"]'); +var d=0;n(c,function(a){h(a);x.La(a,b);a.setAttribute("import-dependency","");"script"===a.localName&&!a.src&&a.textContent&&(a.setAttribute("src","data:text/javascript;charset=utf-8,"+encodeURIComponent(a.textContent+("\n//# sourceURL="+b+(d?"-"+d:"")+".js\n"))),a.textContent="",d++)});return a};k.prototype.L=function(){var a=this;if(!this.b){this.c.disconnect();this.flatten(document);var b=!1,c=!1,d=function(){c&&b&&(a.loadImports(document),a.b||(a.c.observe(document.head,{childList:!0,subtree:!0}), +a.Pa()))};this.Ua(function(){c=!0;d()});this.Ta(function(){b=!0;d()})}};k.prototype.flatten=function(a){var b=this;a=m(a,"link[rel=import]");n(a,function(a){var c=b.a[a.href];(a.__import=c)&&c.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&(b.a[a.href]=a,a.readyState="loading",a.__import=a,b.flatten(c),a.appendChild(c))})};k.prototype.Ta=function(a){function b(e){if(e]/g;function hc(a){switch(a){case "&":return"&";case "<":return"<";case ">":return">";case '"':return""";case "\u00a0":return" "}}function ic(a){for(var b={},c=0;c";break a;case Node.TEXT_NODE:g=g.data;g=k&&kc[k.localName]?g:g.replace(gc,hc);break a;case Node.COMMENT_NODE:g="\x3c!--"+g.data+"--\x3e";break a;default:throw window.console.error(g), +Error("not implemented");}}c+=g}return c};var B={},D=document.createTreeWalker(document,NodeFilter.SHOW_ALL,null,!1),E=document.createTreeWalker(document,NodeFilter.SHOW_ELEMENT,null,!1);function mc(a){var b=[];D.currentNode=a;for(a=D.firstChild();a;)b.push(a),a=D.nextSibling();return b}B.parentNode=function(a){D.currentNode=a;return D.parentNode()};B.firstChild=function(a){D.currentNode=a;return D.firstChild()};B.lastChild=function(a){D.currentNode=a;return D.lastChild()};B.previousSibling=function(a){D.currentNode=a;return D.previousSibling()}; +B.nextSibling=function(a){D.currentNode=a;return D.nextSibling()};B.childNodes=mc;B.parentElement=function(a){E.currentNode=a;return E.parentNode()};B.firstElementChild=function(a){E.currentNode=a;return E.firstChild()};B.lastElementChild=function(a){E.currentNode=a;return E.lastChild()};B.previousElementSibling=function(a){E.currentNode=a;return E.previousSibling()};B.nextElementSibling=function(a){E.currentNode=a;return E.nextSibling()}; +B.children=function(a){var b=[];E.currentNode=a;for(a=E.firstChild();a;)b.push(a),a=E.nextSibling();return b};B.innerHTML=function(a){return lc(a,function(a){return mc(a)})};B.textContent=function(a){switch(a.nodeType){case Node.ELEMENT_NODE:case Node.DOCUMENT_FRAGMENT_NODE:a=document.createTreeWalker(a,NodeFilter.SHOW_TEXT,null,!1);for(var b="",c;c=a.nextNode();)b+=c.nodeValue;return b;default:return a.nodeValue}};var nc=Object.getOwnPropertyDescriptor(Element.prototype,"innerHTML")||Object.getOwnPropertyDescriptor(HTMLElement.prototype,"innerHTML"),oc=document.implementation.createHTMLDocument("inert"),pc=Object.getOwnPropertyDescriptor(Document.prototype,"activeElement"),qc={parentElement:{get:function(){var a=this.__shady&&this.__shady.parentNode;a&&a.nodeType!==Node.ELEMENT_NODE&&(a=null);return void 0!==a?a:B.parentElement(this)},configurable:!0},parentNode:{get:function(){var a=this.__shady&&this.__shady.parentNode; +return void 0!==a?a:B.parentNode(this)},configurable:!0},nextSibling:{get:function(){var a=this.__shady&&this.__shady.nextSibling;return void 0!==a?a:B.nextSibling(this)},configurable:!0},previousSibling:{get:function(){var a=this.__shady&&this.__shady.previousSibling;return void 0!==a?a:B.previousSibling(this)},configurable:!0},className:{get:function(){return this.getAttribute("class")||""},set:function(a){this.setAttribute("class",a)},configurable:!0},nextElementSibling:{get:function(){if(this.__shady&& +void 0!==this.__shady.nextSibling){for(var a=this.nextSibling;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}return B.nextElementSibling(this)},configurable:!0},previousElementSibling:{get:function(){if(this.__shady&&void 0!==this.__shady.previousSibling){for(var a=this.previousSibling;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}return B.previousElementSibling(this)},configurable:!0}},rc={childNodes:{get:function(){if(vb(this)){if(!this.__shady.childNodes){this.__shady.childNodes= +[];for(var a=this.firstChild;a;a=a.nextSibling)this.__shady.childNodes.push(a)}var b=this.__shady.childNodes}else b=B.childNodes(this);b.item=function(a){return b[a]};return b},configurable:!0},childElementCount:{get:function(){return this.children.length},configurable:!0},firstChild:{get:function(){var a=this.__shady&&this.__shady.firstChild;return void 0!==a?a:B.firstChild(this)},configurable:!0},lastChild:{get:function(){var a=this.__shady&&this.__shady.lastChild;return void 0!==a?a:B.lastChild(this)}, +configurable:!0},textContent:{get:function(){if(vb(this)){for(var a=[],b=0,c=this.childNodes,d;d=c[b];b++)d.nodeType!==Node.COMMENT_NODE&&a.push(d.textContent);return a.join("")}return B.textContent(this)},set:function(a){if("undefined"===typeof a||null===a)a="";switch(this.nodeType){case Node.ELEMENT_NODE:case Node.DOCUMENT_FRAGMENT_NODE:for(;this.firstChild;)this.removeChild(this.firstChild);(0b.__shady.assignedNodes.length&&(b.__shady.ia=!0)}b.__shady.ia&&(b.__shady.ia=!1,od(this,b))}a=this.o;b=[];for(c=0;cb.indexOf(d))||b.push(d);for(a=0;a "+b}))}a=a.replace(Df,function(a,b,c){return'[dir="'+c+'"] '+b+", "+b+'[dir="'+c+'"]'});return{value:a,Ka:b,stop:f}}function Bf(a,b){a=a.split(Ef);a[0]+=b;return a.join(Ef)} +function Af(a,b){var c=a.match(Ff);return(c=c&&c[2].trim()||"")?c[0].match(Gf)?a.replace(Ff,function(a,c,f){return b+f}):c.split(Gf)[0]===b?c:Hf:a.replace(wf,b)}function If(a){a.selector===Jf&&(a.selector="html")}hf.prototype.c=function(a){return a.match(zf)?this.b(a,Kf):Bf(a.trim(),Kf)};q.Object.defineProperties(hf.prototype,{a:{configurable:!0,enumerable:!0,get:function(){return"style-scope"}}}); +var uf=/:(nth[-\w]+)\(([^)]+)\)/,Kf=":not(.style-scope)",sf=",",xf=/(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=[])+)/g,Gf=/[[.:#*]/,wf=":host",Jf=":root",zf="::slotted",vf=new RegExp("^("+zf+")"),Ff=/(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/,Cf=/(?:::slotted)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/,Df=/(.*):dir\((?:(ltr|rtl))\)/,qf=".",Ef=":",mf="class",Hf="should_not_match",W=new hf;function Lf(a,b,c,d){this.w=a||null;this.b=b||null;this.ja=c||[];this.G=null;this.P=d||"";this.a=this.u=this.B=null}function X(a){return a?a.__styleInfo:null}function Mf(a,b){return a.__styleInfo=b}Lf.prototype.c=function(){return this.w};Lf.prototype._getStyleRules=Lf.prototype.c;var Nf,Of=window.Element.prototype;Nf=Of.matches||Of.matchesSelector||Of.mozMatchesSelector||Of.msMatchesSelector||Of.oMatchesSelector||Of.webkitMatchesSelector;var Pf=navigator.userAgent.match("Trident");function Qf(){}function Rf(a){var b={},c=[],d=0;af(a,function(a){Sf(a);a.index=d++;a=a.i.cssText;for(var c;c=Ve.exec(a);){var e=c[1];":"!==c[2]&&(b[e]=!0)}},function(a){c.push(a)});a.b=c;a=[];for(var e in b)a.push(e);return a} +function Sf(a){if(!a.i){var b={},c={};Tf(a,c)&&(b.v=c,a.rules=null);b.cssText=a.parsedCssText.replace(Ye,"").replace(Te,"");a.i=b}}function Tf(a,b){var c=a.i;if(c){if(c.v)return Object.assign(b,c.v),!0}else{c=a.parsedCssText;for(var d;a=Te.exec(c);){d=(a[2]||a[3]).trim();if("inherit"!==d||"unset"!==d)b[a[1].trim()]=d;d=!0}return d}} +function Uf(a,b,c){b&&(b=0<=b.indexOf(";")?Vf(a,b,c):ff(b,function(b,e,f,h){if(!e)return b+h;(e=Uf(a,c[e],c))&&"initial"!==e?"apply-shim-inherit"===e&&(e="inherit"):e=Uf(a,c[f]||f,c)||f;return b+(e||"")+h}));return b&&b.trim()||""} +function Vf(a,b,c){b=b.split(";");for(var d=0,e,f;d *"===f||"html"===f,g=0===f.indexOf(":host")&&!h;"shady"===c&&(h=f===e+" > *."+e||-1!==f.indexOf("html"),g=!h&&0===f.indexOf(e));"shadow"===c&&(h=":host > *"===f||"html"===f,g=g&&!h);if(h||g)c=e,g&&(R&&!b.m&&(b.m=rf(W,b,W.b,a?qf+a:"",e)),c=b.m||e),d({Xa:c,Qa:g,hb:h})}} +function Yf(a,b){var c={},d={},e=b&&b.__cssBuild;af(b,function(b){Xf(a,b,e,function(e){Nf.call(a.b||a,e.Xa)&&(e.Qa?Tf(b,c):Tf(b,d))})},null,!0);return{Wa:d,Oa:c}} +function Zf(a,b,c,d){var e=V(b),f=pf(e.is,e.P),h=new RegExp("(?:^|[^.#[:])"+(b.extends?"\\"+f.slice(0,-1)+"\\]":f)+"($|[.:[\\s>+~])");e=X(b).w;var g=$f(e,d);return nf(b,e,function(b){var e="";b.i||Sf(b);b.i.cssText&&(e=Vf(a,b.i.cssText,c));b.cssText=e;if(!R&&!cf(b)&&b.cssText){var k=e=b.cssText;null==b.ra&&(b.ra=We.test(e));if(b.ra)if(null==b.W){b.W=[];for(var n in g)k=g[n],k=k(e),e!==k&&(e=k,b.W.push(n))}else{for(n=0;n=l._useCount&&l.parentNode&&l.parentNode.removeChild(l));R?f.a?(f.a.textContent=e,d=f.a):e&&(d=df(e,g,a.shadowRoot,f.b)):d?d.parentNode|| +(Pf&&-1.\n var capturedCloneNode = Node.prototype.cloneNode;\n var capturedCreateElement = Document.prototype.createElement;\n var capturedImportNode = Document.prototype.importNode;\n var capturedRemoveChild = Node.prototype.removeChild;\n var capturedAppendChild = Node.prototype.appendChild;\n var capturedReplaceChild = Node.prototype.replaceChild;\n var capturedParseFromString = DOMParser.prototype.parseFromString;\n var capturedHTMLElementInnerHTML = Object.getOwnPropertyDescriptor(window.HTMLElement.prototype, 'innerHTML');\n var capturedChildNodes = Object.getOwnPropertyDescriptor(window.Node.prototype, 'childNodes');\n\n var elementQuerySelectorAll = Element.prototype.querySelectorAll;\n var docQuerySelectorAll = Document.prototype.querySelectorAll;\n var fragQuerySelectorAll = DocumentFragment.prototype.querySelectorAll;\n\n var scriptSelector = 'script:not([type]),script[type=\"application/javascript\"],script[type=\"text/javascript\"]';\n\n function QSA(node, selector) {\n // IE 11 throws a SyntaxError with `scriptSelector` if the node has no children due to the `:not([type])` syntax\n if (!node.childNodes.length) {\n return [];\n }\n switch (node.nodeType) {\n case Node.DOCUMENT_NODE:\n return docQuerySelectorAll.call(node, selector);\n case Node.DOCUMENT_FRAGMENT_NODE:\n return fragQuerySelectorAll.call(node, selector);\n default:\n return elementQuerySelectorAll.call(node, selector);\n }\n }\n\n // returns true if nested templates cannot be cloned (they cannot be on\n // some impl's like Safari 8 and Edge)\n // OR if cloning a document fragment does not result in a document fragment\n var needsCloning = (function() {\n if (!needsTemplate) {\n var t = document.createElement('template');\n var t2 = document.createElement('template');\n t2.content.appendChild(document.createElement('div'));\n t.content.appendChild(t2);\n var clone = t.cloneNode(true);\n return (clone.content.childNodes.length === 0 || clone.content.firstChild.content.childNodes.length === 0\n || brokenDocFragment);\n }\n })();\n\n var TEMPLATE_TAG = 'template';\n var PolyfilledHTMLTemplateElement = function() {};\n\n if (needsTemplate) {\n\n var contentDoc = document.implementation.createHTMLDocument('template');\n var canDecorate = true;\n\n var templateStyle = document.createElement('style');\n templateStyle.textContent = TEMPLATE_TAG + '{display:none;}';\n\n var head = document.head;\n head.insertBefore(templateStyle, head.firstElementChild);\n\n /**\n Provides a minimal shim for the