diff --git a/src/GS009/01_harjoitus_1.Rmd b/src/GS009/01_harjoitus_1.Rmd new file mode 100644 index 00000000..fb1db99c --- /dev/null +++ b/src/GS009/01_harjoitus_1.Rmd @@ -0,0 +1,301 @@ +# Harjoitus 1: Työkalujen käyttöönotto + +**Harjoituksen sisältö** - Harjoituksessa tutustutaan pgAdmin 4 -käyttöliittymään sekä psql:ään. Lisäksi harjoituksessa luodaan uusi paikkatietokanta. + +**Harjoituksen tavoite** - Harjoituksen jälkeen opiskelija hallitsee pgAdmin 4 -käyttöliittymän ja psql:n perusteet. + +## Harjoitus 1.1: pgAdmin 4 + +Käynnistä pgAdmin 4 -ohjelmisto menemällä osoitteeseen +[/pgadmin](/pgadmin). Pääset kirjautumaan etäpalvelimen pgAdminiin +seuraavilla tunnuksilla: + +TODO: päivitä ohjeet kirjautumiseen + +![pgAdmin- kirjautuminen](img/pgadmin_splash.png) + +### Tietokantayhteyden lisääminen + +Liitä pgAdmin-ohjelmaan koulutusympäristön tietokanta klikkaamalla +hiiren oikealla kohdasta **Servers** ja valitsemalla **Register \> +Server...** + +TODO: päivitä ohjeet kirjautumiseen + +Syötä seuraavat tiedot: + +- General-välilehdellä + - Name: yhteyden nimi (tyypillisesti \\@\) + - Connection-välilehdellä + - Host: **dbhost** + - Port: **5432** + - Maintenance database: **postgres** +- Valitse **Save password**, jos et halua kirjoittaa salasanaa uudelleen aina avatessasi yhteyden + +Voit tarkastella asennettua tietokantaa pgAdmin:n avulla yläpalkin eri +välilehdiltä: + +![](img/pgadylapalkki.png) + +PostGIS-tietokantoja voidaan hyödyntää pgAdmin:n lisäksi myös muissa +sovelluksissa (psql-komentorivin tai QGISin **Tietokannan hallinta (DB +Manager)** -lisäosan kautta). Tältä tietokanta näyttää QGISin +**Tietokannan hallinnassa**: + +![](img/qgisDbmanager.png) + +### Harjoitustietokannan luonti + +Luodaan koulutusta varten **trainingdatabase**-niminen +harjoitustietokanta. Tämän voi tehdä pgAdmin:n **graafisen +käyttöliittymän** kautta: + +![](img/pgadmindbluo.png) + +:::hint-box +**Huom!** Tietokannan voi luoda ja poistaa myös seuraavien SQL-lauseiden avulla: + +**CREATE DATABASE** trainingdatabase;\ +**DROP DATABASE** trainingdatabase; + +::: + +### SQL-komentojen suorittaminen + +Koulutuksessa tullaan suorittamaan useita harjoituksia SQL-komentokielen +avulla. pgAdmin:n **Kysely-työkalun (Query Tool)** avulla voit suorittaa +SQL-kyselyitä ja lausekkeita. **Query Tool** käynnistetään seuraavasti: + +- Valitse **Servers**-osiosta oma tietokantaklusterisi +- Valitse klusterin sisältä haluamasi tietokanta (**trainingdatabase**) +- Valitse ylhäältä **Tools \> Query Tool** + +Haluttu SQL-komento suoritetaan painamalla avautuvasta **Query Tool** +-ikkunasta löytyvää kolmio-painiketta (**Execute/Refresh**) tai +**F5**-näppäintä. Jos haluat suorittaa vain osan SQL-lausekkeesta, +väritä hiirellä mieleisesi osio ja paina **F5**. Näet alaikkunassa +komennon tuloksen. Voit myös tallentaa SQL-komentosi +**.sql**-tiedostoon, josta ne voi myöhemmin ladata. + +![](img/pgadmin_query_tool.gif) + +Nyt lisätään PostGIS-lisäosa **trainingdatabase**-tietokantaan +seuraavalla SQL-komennolla: + +::: code-box +``` sql +CREATE EXTENSION IF NOT EXISTS postgis; +``` +::: + +Hienoa! Olet asentanut PostGIS-lisäosan joka mahdollistaa muun muassa paikkatietojen tallennuksen ja analysoinnin tietokantaan. + +::: hint-box +Mitä spatial_ref_sys-taulu sisältää? + +Mitä näkymiä (views) on tietokantaan muodostunut? Mitä tietoja ne +sisältävät? +::: + + +Uusi taulu voidaan luoda kirjoittamalla seuraava SQL-komentojono **Query Tool**:n SQL-editoriin. + +::: code-box +``` sql +-- PostgreSQL ja PostGISin perusteet +CREATE TABLE test_tmp( + id serial, + time time, + num integer); +``` +::: + +::: hint-box +Huomaa, että kahdella viivalla "\-\-" alkavat rivit ovat +kommenttirivejä, eikä niitä oteta huomioon SQL-komentoa +suoritettaessa. +::: + +Tauluja voi luoda myös SQL-kyselyiden tulosten perusteella. + +Lisätään yllä luotuun tauluun tietueita seuraavalla SQL-komennolla: + +::: code-box +``` sql +INSERT INTO test_tmp (time,num) +(SELECT now(), generate_series(1,5000)); +``` +::: + +Tietueita voi lisätä myös SQL-kyselyjen tulosten perusteella. + +Voit listata tauluusi tekemiä tietueita esimerkiksi seuraavalla +komennolla: + +::: code-box +``` sql +SELECT * +FROM test_tmp +LIMIT 10; +``` +::: + +Voit poistaa luodun taulun seuraavalla komennolla: + +::: code-box +``` sql +DROP TABLE test_tmp; +``` +::: + +### pg_dump ja pg_restore + +Tietokannan tai yksittäisten taulujen varmuuskopioiden luomiseen ja +palauttamiseen on omat komentoriviohjelmansa: +[pg_dump](https://www.postgresql.org/docs/13/app-pgdump.html) ja +[pg_restore](https://www.postgresql.org/docs/13/app-pgrestore.html). +Muun muassa pgAdmin käyttää näitä sisäisesti. + +## Harjoitus 1.2: psql + +SQL-komentoja voi suorittaa pgAdminin (ja QGISin Tietokannan hallinta +-lisäosan) lisäksi myös psql-komentorivin kautta. Avaa +[komentorivi](/wetty), jotta pääset käyttämään +psql-komentorivityökalua. Kirjaudu ensin sisään WeTTY- terminaaliemulaattoriin: + +TODO: päivitä ohjeet kirjautumiseen + +Ota yhteys omaan tietokantaklusteriisi +komennolla: + + +::: commandline-box +``` sh +psql -U postgres -h dbhost +``` +::: + + +![](img/psql_start.png) + +### psql:n käyttäminen + +Kun psql on käynnistetty, komentoriville voi kirjoittaa sekä psql- että +SQL-komentoja. psql-session aikana käytettäviä komentoja kutsutaan +psql-interaktiivisiksi. + +Alla muutama esimerkki interaktiivisista psql-komennoista: + +::: commandline-box +``` psql +\d = näytä taulut, näkymät ja sekvenssit +\dg = näytä tietokantaklusterin roolit (käyttäjät) +\c tietokannan_nimi = yhdistä tietokannan_nimi -tietokantaan +``` +::: + +Voit nyt ottaa yhteyttä trainingdatabse-tietokantaan: + +::: commandline-box +``` psql +\c trainingdatabse +``` +::: + +Komennolla `help` ja erityisesti komennolla `\?` saat tietoa ohjelman +eri komennoista. Pääset pois listauksesta painamalla `q`. + +Komentorivin puolella käytettäviä psql-komentoja kutsutaan +ei-interaktiivisiksi. Ei-interaktiivisia psql-komentoja käytetään +silloin kun halutaan käyttää psql:aa suoraan käyttöjärjestelmän +komentorivista ja valittavat psql-komennot sekä SQL-skriptit ovat +tiedostossa. Ei-interaktiivinen psql soveltuu erityisen hyvin tehtävien +automaatisointiin. Edellä mainitut yhteydenottokomennot ovat oivia +esimerkkejä ei-interaktiivisista psql-komennoista. Kokeile ajaa seuraava +komento komentorivillä: + +::: commandline-box +``` sh +psql -U postgres -h dbhost -c "select current_database();" +``` +::: + +### Tietokannan luonti + +createdb on komentorivityökalu helpottamaan tietokannan luomista. +Helpoimmillaan uuden tietokannan luominen onnistuukin komennolla: + +::: commandline-box +``` sh +createdb -U postgres -h dbhost uuden_tietokannan_nimi +``` +::: + +![](img/createdb.png) + +### Tietokannan poistaminen + +dropdb samoin kuin createdb on komentorivityökalu. Helpoimmillaan +tietokannan voi poistaa komennolla: + +::: commandline-box +``` sh +dropdb -U postgres -h dbhost poistettavan_tietokannan_nimi +``` +::: + +### Tietokantayhteyden sulkeminen + +Kun haluat sulkea tietokantayhteyden, anna psql-ohjelmassa komento: + +::: commandline-box +`\q` +::: + +### Tiedot asennuksista + +PostgreSQL:n version voit kysyä SQL-komennolla: + +::: code-box +``` sql +SELECT version(); +``` +::: + +Asennetut lisäosat voit tarkistaa SQL-lauseella: + +::: code-box +``` sql +SELECT * +FROM pg_extension; +``` +::: +### Tietokantayhteyden sulkeminen + +Klikkaa hiiren oikealla luomasi yhteyden päällä ja valitse **Disconnect +from server**. + +### Muita huomioita + +Jos haluat käyttää PostGIS-tietokantaa muilta tietokoneilta, tulee +PostgreSQL:n määrittelytiedostoon (pg_hba.conf) tehdä muutamia +tarvittavia muutoksia, esimerkiksi seuraavasti: + +::: code-box +``` mysql +# IPv4 local connections: +#host all all 127.0.0.1/32 md5 +host all all 0.0.0.0/0 trust +``` +::: + +Muutokset on tehty koulutuksessa käytettävälle PostgreSQL-asennukselle +jo valmiiksi. + +::: hint-box +**HUOM!** Tämä muutos mahdollistaa yhteydenoton mistä tahansa tietokoneesta ja +on turvallisuusriski tuotannollisissa tietojärjestelmissä. +::: + +Oletuksena yhteys tietokantaan on suojaamaton. Tietokantayhteys +suositellaan salattavaksi TLS:n avulla. diff --git a/src/GS009/02_harjoitus_2.Rmd b/src/GS009/02_harjoitus_2.Rmd new file mode 100644 index 00000000..290dbb98 --- /dev/null +++ b/src/GS009/02_harjoitus_2.Rmd @@ -0,0 +1,226 @@ +# Harjoitus 2: Aineistojen lataaminen + +**Harjoituksen sisältö** - Harjoituksessa ladataan paikkatietoaineistoja PostGIS- tietokantaan. + +**Harjoituksen tavoite** - Harjoituksen jälkeen opiskelijalla on perustiedot paikkatietoaineistojen lataamiseen paikkatietokantaan. + +### Valmistautuminen + +QGIS tulee olla asennettuna, jotta paikkatietoaineistoja voidaan ladata. Avaa myös [pgAdmin](/pgadmin) selaimeen ja kirjaudu sisään. Avaa **Query Tool** (Valitse _trainingdatabase_ **->** Ylhäältä **Tools** **->** **Query Tool**). + +## Harjoitus 2.1: Tekstitiedoston lataaminen + +Monia pistemäisiä paikkatietoaineistoja on tallennettu CSV-tiedostoihin, jossa ne eivät varsinaisesti ole paikkatietomuodossa. Ensimmäisessä harjoituksessa ladataan globaali lentokenttiä kuvaava aineisto PostgreSQL-tietokantaan. Luodaan ensin harjoitustietokantaan taulu seuraavasti: + +::: code-box +``` sql +DROP TABLE IF EXISTS airports; + +CREATE TABLE airports +( + id integer, + name text, + city text, + country text, + IATA_code char(3), + ICAO_code char(4), + latitude numeric, + longitude numeric, + altitude numeric, + timezone text, + dst text, + tz_zone text, + type text, + source text +); +``` +::: + +Kyseinen aineisto on ladattu valmiiksi [OpenFlights.org-sivustolta](http://openflights.org/data.html) päänäkymän data-kansioon. + +Tarkastele miltä kyseinen aineisto näyttää kansiossa. Voit avata tiedoston selaimeen [tästä linkistä](/data/airports.dat). + +Voit lukea CSV-tiedoston tiedot edellisessä vaiheessa luotuun tauluun seuravaalla komennolla: + + +::: code-box +``` sql +COPY airports +FROM '/home/student/data/airports.dat' +WITH CSV; +``` +::: + + +**COPY**-komento viittaa tiedostoon kovalevyllä ja lataa sen. **COPY** voi viitata CSV:n lisäksi myös esimerkiksi [binääriformaatteihin tai tekstitiedostoihin.](https://www.postgresql.org/docs/current/sql-copy.html) + +Tarkista lopuksi, että tietokantataulussa on dataa. + +::: code-box +``` sql +SELECT * +FROM airports +LIMIT 10; +``` +::: + +Aineistoa tarkastelemalla nähdään, että taulussa on koordinaatteja, mutta ne on tallennettu vain numeroarvoina; ei paikkatietotyyppinä. + +Jotta PostGIS:n toiminnallisuuksia voisi hyödyntää aineiston kanssa, tulee kyseiseen tauluun lisätä geometriasarake. PostGIS:ssä on valmis [funktio](https://postgis.net/docs/AddGeometryColumn.html) tähän tarkoitukseen. Tarkastele dokumentaatiosta miten kyseistä funktiota käytetään. + +::: code-box +``` sql +SELECT AddGeometryColumn ('airports','geom',4326,'POINT',2); +``` +::: + +Tarkastele taulua uudelleen. + +::: code-box +``` sql +SELECT * +FROM airports +LIMIT 10; +``` +::: + +Tauluun on ilmestynyt uusi sarake. Sarake ei kuitenkaan sisällä vielä mitään tietoa. Päivitetään taulun sisältö **UPDATE**-komennon avulla. + +Seuraavassa komennossa on ketjutettu useampi funktio sisäkkäin. + +- [ST_MakePoint](https://postgis.net/docs/ST_MakePoint.html) luo tekstikenttien perusteella pistemuotoisen geometrian +- [ST_SetSRID](https://postgis.net/docs/ST_SetSRID.html) asettaa kyseiselle tietokentälle EPSG-koodin avulla koordinaattijärjestelmän + +::: code-box +``` sql +UPDATE airports +SET geom = ST_SetSRID(ST_MakePoint(longitude, latitude),4326); +``` +::: + +Tarkastele lopuksi aineistoa esimerkiksi pgAdminin karttatoiminnallisuuden avulla. + +![](img/pgadmin_geom.png) + +## Harjoitus 2.2: Paikkatietoaineiston lataaminen + +Maanmittauslaitoksen aineisto on ladattu valmiiksi harjoitussivun [data-kansioon](/data). + +### Vaihtoehto 1: QGISin tietokannan hallinnan avulla + +QGIS-työpöytäohjelmisto tarjoaa erittäin kätevän graafisen käyttöliittymän paikkatietoaineistojen lataamiseksi PostGIS-tietokantaan. Useat QGISin eri työkalut mahdollistavat joustavan latauksen ja mahdolliset muokkaukset aineistoon jo ennen latausta. + +Ensimmäisessä vaiheessa otetaan yhteys lokaalista QGIS-asennuksesta koulutuksessa käytettävään PostGIS-tietokantaan. Avaa tässä vaiheessa QGIS, jos et ole sitä jo tehnyt. Lisää uusi tietokantayhteys avaamalla QGISin tietolähteiden hallinta klikkaamalla Tasot \> Tietolähteiden hallinta. Valitse Tietolähteiden hallinta -ikkunasta PostgreSQL-välilehti ja klikkaa Uusi-painiketta. + +Syötä Yhteyden tiedot -ikkunaan seuraavat tiedot tietokantayhteyden määrittämiseksi: + +![](img/yhteyspg.png) + +Huomaa, että Name-kenttä kuvaa vain QGISiin tallennettavan yhteyden nimeä eikä itse tietokannan nimeä. Yhteyden valinnaisista toiminnallisuuksista kannattaa oletuksena valita kaikki, paitsi "Älä ratkaise rajoittamattomien sarakkeidein tyyppiä (GEOMETRIA)". Jos se on päällä niin emme näe näkymää jota luodaan harjoituksessa 8. Esimerkiksi arvioidun metadatan käyttäminen nopeuttaa hakuja huomattavasti. + +Paina **Testaa yhteyttä** -painiketta varmistaaksesi tietokantayhteyden toiminnan ja paina **OK**. QGISin sisällä voi myös ajaa SQL-komentoja esimerkiksi **DB Manager**in avulla. + +Luo tässä vaiheessa trainingdatabase-tietokantaan uusi skeema, jonne Maanmittauslaitoksen aineistot tullaan lataamaan, ja anna skeemalle nimeksi "nlsfi". Skeemojen avulla on helpompi pitää aineistot järjestyksessä. Uuden skeeman voi luoda pgAdminin graafisen käyttöliittymän kautta, QGISin kautta tai seuraavalla SQL-komennolla: + +::: code-box +``` sql +CREATE SCHEMA IF NOT EXISTS nlsfi; +``` +::: + +Jos et saa luomaasi skeemaa näkyviin QGISin puolella, aja seuraavat sql- komennot ja käynnistä QGIS-projekti uudelleen. + +::: code-box +``` sql +DROP TABLE IF EXISTS nlsfi.example; + +CREATE TABLE nlsfi.example +( + id integer, + name text +); +``` +::: + +::: code-box +``` sql +INSERT INTO nlsfi.example +VALUES (1, 'testi'); +``` +::: + +Lataa [data-kansio](/data/Maastokartta_1m.zip) omalle koneellesi. Aineistoja voi lisätä navigoimalla Tasot \> Lisää taso \> Lisää vektoritaso, klikkaamalla Lisää vektoritaso -kuvaketta tasojen hallinnan työkalupalkista tai ihan vain raahaamalla tasoja suoraan Selain-ikkunasta Tasot-ikkunaan. + +Lataa projektiisi ja tietokantaasi (ainakin) seuraavat aineistot: + +- TieViiva.shp +- HallintoAlue.shp +- KarttanimiPiste1000.shp +- SahkoLinja.shp +- LentokenttaPiste.shp +- RautatieViiva.shp + +::: hint-box +Tarkista, että Koodaus-kohdassa on valittu UTF-8. Mikäli aineisto koodataan jollakin toisella järjestelmällä, ääkköset puuttuvat metatiedoista. +::: + +QGIS-projektiin avautuu vektoriaineistoja, johon on määritelty tietty koordinaattijärjestelmä. Tarkista, että koordinaattijärjestelmäksi on määritelty ETRS89 / TM35FIN(E,N) (EPSG:3067) tai EPSG:3047. Tason koordinaattijärjestelmän voit tarkistaa ja muuttaa klikkaamalla hiiren oikeaa painiketta tasolla ja valitsemalla **Ominaisuudet \> Lähde \> Aseta koordinaattijärjestelmä**. Kannattaa myös asettaa EPSG:3067 QGIS-projektin koordinaattijärjestelmäksi. Asettaminen tapahatuu QGIS ikkunan oikeassa alakulmassa. + +![](img/qgistasot.png) + +Avaa QGISin prosessointityökaluista työkalu nimeltä Export to PostgreSQL. Avaa työkalun alapalkista **Aja eräajona** (Run as Batch Process), joka mahdollistaa useamman taulun ajamiseen tietokantaan kerralla. Muuta parametreja niin, että aineistot tulee ladattua oikeaan skeemaan ja tietokantaan. **Täytä** (Fill Down) -toimintoa käyttämällä sinun ei tarvitse klikkailla jokaisen tason kohdalta arvoja kuntoon. Lisää geometriasarakkeen nimeksi "wkb_geometry" ja, varmistaaksesi taulujen nimien kirjaantumisen pienillä kirjaimilla, avaa taulun nimen määrittävässä kohdassa lausekkeenmuodostaja ja kopioi siihen komento: + +::: code-box +``` sql +lower(layer_property( @INPUT, 'name')) +``` +::: + +Tarkista mitä muita parametrejä prosessi pitää sisällään. Voit kuitenkin jättää ne oletusarvoisiksi. Lopulta latausprosessisi pitäisi näyttää kutakuinkin tältä. Klikkaa **Run**! + +![](img/batchrun.png) Tarkista latauksen jälkeen, että aineistot ovat latautuneet. Tarkista virheilmoitukset ja korjaa latausta tarvittaessa. + +::: code-box +``` sql +SELECT * +FROM nlsfi.tieviiva +LIMIT 10; +``` +::: + +### Vaihtoehto 2: Komentorivin avulla + +Luo tässä vaiheessa harjoitustietokantaan uusi skeema, jonne Maanmittauslaitoksen aineistot tullaan lataamaan, ja anna skeemalle nimeksi "nlsfi". Skeemojen avulla on helpompi pitää aineistot järjestyksessä. Uuden skeeman voi luoda pgAdminin graafisen käyttöliittymän kautta tai seuraavalla SQL-komennolla: + +::: code-box +``` sql +CREATE SCHEMA IF NOT EXISTS nlsfi; +``` +::: + +Komentoriviltä tapahtuvaan lataamiseen käytetään **shp2pgsql**-ohjelmaa tai **ogr2ogr**-työkalua. Käynnistämällä ohjelman ilman parametrejä saat opasteen eri parametreistä. Tämän jälkeen voit ladata aineistoa äsken luotuun skeemaan **ogr2ogr**-työkalulla. Jos koneellasi on asennettu OSGeo4W-paketti (tulee QGIS:n asennuksen mukana), avaa käynnistysvalikosta **OSGeo4W Shell** ja anna seuraava komento: + +::: commandline-box +``` sh +ogr2ogr -f "PostgreSQL" PG:"host= dbname= user= password=" \tiedostonimi.shp -lco SCHEMA=nlsfi +``` +::: + +Muista tarkistaa, että aineiston hakemistopolku ja muut parametrit ovat kunnossa! + +**ogr2ogr**-komennon käyttämät parametrit ovat: + +::: commandline-box +``` +-f output file format name +-lco layer creation option +``` +::: + +Muita parametreja voit tutkia suorittamalla **ogr2ogr**-komennon ilman parametrejä. PostGIS-asennuksen yhteydessä usein asennettavalla **shp2pgsql**-työkalulla on myös mahdollista luoda shp-tiedostoista SQL-muotoisia lataustiedostoja. Komentorivityökalut mahdollistavat useamman tiedoston lataamisen tietokantaan kätevästi yhdellä kertaa. Esimerkiksi Windows-ympäristössä on mahdollista ladata kansiollisen gml-tiedostoja kerralla tietokantaan seuraavalla komennolla: + +::: commandline-box +``` sh +for %i in (*.gml) do ogr2ogr -update -append -f PostgreSQL PG:"host= port=5432 dbname= user= password= schemas=gml" %i +``` +::: \ No newline at end of file diff --git a/src/GS009/03_harjoitus_3.Rmd b/src/GS009/03_harjoitus_3.Rmd new file mode 100644 index 00000000..b4bcd91b --- /dev/null +++ b/src/GS009/03_harjoitus_3.Rmd @@ -0,0 +1,373 @@ +# Harjoitus 3: SQL:n perusteet + +**Harjoituksen sisältö** - Harjoituksessa tehdään muutamia SQL-hakuja. + +**Harjoituksen tavoite** - Harjoituksen tarkoituksena on tutustua SQL-kieleen. + +### Valmistautuminen + +Avaa [pgAdmin](/pgadmin) selaimeen ja kirjaudu sisään. Avaa **Query Tool** (Valitse _trainingdatabase_ **->** Ylhäältä **Tools** **->** **Query Tool**). + +### Yksinkertaisia SQL-hakuja + +## Harjoitus 3.1 + +Seuraavaksi tutkitaan hiukan edellisessä harjoituksessa ladattuja paikkatietoaineistoja: + +:::code-box +```sql +SELECT +kunta_ni1 +FROM +nlsfi.hallintoalue; +``` +::: + +Hakuja voidaan rajoittaa **WHERE**–lausekkeella: + +:::code-box +```sql +SELECT +kunta_ni1, wkb_geometry +FROM +nlsfi.hallintoalue +WHERE +maaku_ni1 = 'Lappi'; +``` +::: + +SQL-lauseisiin voidaan myös liittää erilaisia funktioita. Funktioiden avulla voidaan esimerkiksi laskea keskiarvoja tai keskihajontoja. Seuraavassa tarkastellaan kuntien nimien pituuksia: + +:::code-box +```sql +SELECT +avg(char_length(kunta_ni1)), stddev(char_length(kunta_ni1)) +FROM +nlsfi.hallintoalue +WHERE +maaku_ni1 = 'Uusimaa'; +``` +::: + +Seuraavalla SQL-lauseella saamme selville, missä maakunnissa on keskimäärin pisimmät kuntien nimet: + +:::code-box +```sql +SELECT +maaku_ni1, avg(char_length(kunta_ni1)) +FROM +nlsfi.hallintoalue +GROUP BY +maaku_ni1 +ORDER BY +avg(char_length(kunta_ni1)) desc; +``` +::: + +## Harjoitus 3.2 + +Missä maakunnassa on keskimäärin pisimmät kuntien nimet? + +::: code-box +```sql +SELECT +... +FROM +... +GROUP BY +... +ORDER BY +... desc +LIMIT ...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Täydennä tähän kyselyyn oikeat sarakkeet, skeema ja taulu. Tarkista millä funktiolla +-- saat laskettua keskiarvon. Käytä char_length() funktiota, jolla saat palautettua +-- merkkijonon pituuden. +SELECT +maakunta, keskiarvo_funktio(char_length(kunta)) +FROM +skeema.taulu +GROUP BY +maakunta +ORDER BY +keskiarvo_funktio(char_length(kunta)) desc +LIMIT 1; +``` +::: +::: + + + +::: hidden-box +:::code-box +```sql +SELECT +maaku_ni1, avg(char_length(kunta_ni1)) +FROM +nlsfi.hallintoalue +GROUP BY +maaku_ni1 +ORDER BY +avg(char_length(kunta_ni1)) desc +LIMIT 1; +``` +::: +::: + +## Harjoitus 3.3 + +Missä maakunnassa on keskimäärin lyhimmät kuntien nimet? + +:::code-box +```sql +SELECT +... +FROM +... +GROUP BY +... +ORDER BY +... asc +LIMIT ...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Täydennä tähän kyselyyn oikeat sarakkeet, skeema ja taulu. Tarkista millä funktiolla +-- saat laskettua keskiarvon. Käytä char_length() funktiota, jolla saat palautettua +-- merkkijonon pituuden. +SELECT +maakunta, keskiarvo_funktio(char_length(kunta)) +FROM +skeema.taulu +GROUP BY +maakunta +ORDER BY +keskiarvo_funktio(char_length(kunta)) asc +LIMIT 1; +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +maaku_ni1, avg(char_length(kunta_ni1)) +FROM +nlsfi.hallintoalue +GROUP BY +maaku_ni1 +ORDER BY +avg(char_length(kunta_ni1)) asc +LIMIT 1; +``` +::: +::: + +## Harjoitus 3.4 + +Mikä on Suomen pisin kunnan nimi? + +:::code-box +```sql +SELECT +... +FROM +... +ORDER BY +... +LIMIT +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Täydennä tähän kyselyyn oikeat sarakkeet, skeema ja taulu. Valitse funktio, +-- jolla saat tietoon merkkijonon pituuden. +SELECT +kunta +FROM +skeema.taulu +ORDER BY +merkkijonon_pituus(kunta) desc +LIMIT 1; +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +kunta_ni1 as "Kunta" +FROM +nlsfi.hallintoalue +ORDER BY +char_length(kunta_ni1) desc +LIMIT 1; +``` +::: +::: + +## Harjoitus 3.5 + +Montako 5 kirjaimista suomenkielistä kunnan nimeä Suomessa on? Huomioi myös kunnat missä suomi on kakkoskieli(kieli_ni2). + +:::code-box +```sql +WITH ... AS +( + SELECT ... +UNION + SELECT ... +) + +SELECT +... +FROM +...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- käytä CTE (Common Table Expression)- lauseketta +WITH ltr5 AS +( + -- Valitse kunnat, jossa kunnan ykköskieli (kieli_ni1) on 'Suomi' ja kunnan suomenkielinen nimi on + -- viisi merkkiä pitkä. + SELECT + ... + FROM + ... + WHERE + ... AND ... +UNION -- yhdistä kyselyiden tulokset UNION- operaattorilla + -- valitse kunnat, jossa kunnan kakkoskieli (kieli_ni2) on 'Suomi' ja kunnan suomenkielinen nimi on + -- viisi merkkiä pitkä. + -- Huomioi oikea kunnan nimen sarake (kunta_ni1 vai kunta_ni2) + SELECT + ... + FROM + ... + WHERE + ... AND ... +) + +SELECT +count() AS ... -- käytä count() funktiota (valitse yllä määritellystä CTE:stä sopiva sarake). + -- Voit myös määrittää sille aliaksen 'AS'- lausekkeen jälkeen. +FROM +...; -- viittaa aikaisemmin määriteltyyn CTE:hen +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +WITH ltr5 AS +( + SELECT + kunta_ni1 as "Kunta", char_length(kunta_ni1) as "Pituus", + kieli_ni1, 'Ykköskieli' as "Kielisyys" + FROM + nlsfi.hallintoalue + WHERE + char_length(kunta_ni1) = 5 AND kieli_ni1 = 'Suomi' +UNION + SELECT + kunta_ni2 as "Kunta", char_length(kunta_ni2) as "Pituus", + kieli_ni2, 'Kakkoskieli' as "Kielisyys" + FROM + nlsfi.hallintoalue + WHERE + char_length(kunta_ni2) = 5 AND kieli_ni2 = 'Suomi' +) + +SELECT +count("Kunta") AS "5-kirjaimisia suomenkielisiä kunta" +FROM +ltr5; +``` +::: +::: + +## Harjoitus 3.6 + +Missä kunnissa suomen- ja ruotsinkielinen nimi on eri, mutta samanpituinen? Järjestä tulokset kunnan nimen pituuden mukaan laskevasti. + +:::code-box +```sql +SELECT +... +FROM +... +WHERE +... +ORDER BY +... DESC; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Täydennä oikeat sarakkeet +SELECT +kunnan_nimi_fi, kunnan_nimi_sv, char_length(kunnan_nimi_fi) AS "Pituus" +FROM +nlsfi.hallintoalue +WHERE +kunnan_nimi_fi ... kunnan_nimi_sv AND char_length(kunnan_nimi_fi) ... char_length(kunnan_nimi_sv) +-- korvaa tyhjäksi jätetyt kohdat '...' oikeilla operaattoreilla +-- kts. tarvittaessa linkki alhaalta dokumentaatioon +ORDER BY +char_length(kunnan_nimi_fi) DESC; +``` +::: +[Operaattorit PostgreSQL:n dokumentaatiossa.](https://www.postgresql.org/docs/9.0/functions-comparison.html) +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +kunta_ni1, kunta_ni2, char_length(kunta_ni1) AS "Pituus" +FROM +nlsfi.hallintoalue +WHERE +kunta_ni1 <> kunta_ni2 AND char_length(kunta_ni1) = char_length(kunta_ni2) +ORDER BY +char_length(kunta_ni1) DESC; +``` +::: +::: diff --git a/src/GS009/04_harjoitus_4.Rmd b/src/GS009/04_harjoitus_4.Rmd new file mode 100644 index 00000000..af2ad697 --- /dev/null +++ b/src/GS009/04_harjoitus_4.Rmd @@ -0,0 +1,244 @@ +# Harjoitus 4: Spatiaaliset SQL-haut + +**Harjoituksen sisältö** - Harjoituksessa tutustutaan paikkatietojen tallentamisen perusperiaatteisiin ja suoritetaan muutamia spatiaalisia SQL-hakuja. + +**Harjoituksen tavoite** - Harjoituksen jälkeen opiskelijalla on käsitys, kuinka PostGIS-tietokannan spatiaalisia hakuoperaattoreita voidaan käyttää osana paikkatietoanalyysejä. + +### Valmistautuminen + +Avaa [pgAdmin](/pgadmin) selaimeen ja kirjaudu sisään. Avaa **Query Tool** (Valitse *trainingdatabase* **-\>** Ylhäältä **Tools** **-\>** **Query Tool**). + +### Paikkatietojen metatiedot + +Kaikki PostGIS-tietokannassa olevat paikkatietotaulut on rekisteröity metatieto-tauluihin: + +| | | +|:------------------------------:|:--------------------------------------:| +| [**geography_columns**]{style="color:purple"} | Geography-tietotyypin paikkatietotaulut | +| [**geometry_columns**]{style="color:purple"} | Geometry-tietotyypin paikkatietotaulut | +| [**raster_columns**]{style="color:purple"} | Rasteritietoa sisältävät paikkatietotaulut | +| [**raster_overviews**]{style="color:purple"} | Yleistettyjä rasteriaineistoja sisältävät paikkatietotaulut | + +## Harjoitus 4.1: Geometrioiden metatiedot + +Tutki geometry_columns-taulua. Mitä tietoja eri tietokentät sisältävät? + +::: code-box +``` sql +SELECT * +FROM +geometry_columns; +``` +::: + +::: hint-box +Onko geometry_columns taulu? +::: + +## Harjoitus 4.2: Geometrian esittäminen + +Tarkastellaan ensin paikkatietojen tallennusmuotoa PostGIS-paikkatietokannassa. Suorita seuraava SQL-lause: + +::: code-box +``` sql +SELECT +kunta_ni1, maaku_ni1, wkb_geometry +FROM +nlsfi.hallintoalue +WHERE +kunta_ni1 = 'Hanko'; +``` +::: + +Tuloksesta nähdään, että sarakkeen wkb_geometry sisältö on koneluettavassa binäärimuodossa. + +::: hint-box +Vinkki: On mahdollista tarkastella geometrioita suoraan graafisessa käyttöliittymässä klikkaamalla pientä karttaikonia ![](img/pgadmin_geom.png) geometriasarakkeen päällä. Mikäli aineistot ovat WGS84-koordinaattijärjestelmässä (EPSG: 4326), pgAdmin myös lisää niihin suoraan taustakartan OpenStreetMapista. +::: + +Aineistojen koordinaatistot löytyvät SRID-sarakkeesta. Yhdessä SRID-sarakkeessa voi olla vain yhden koordinaatiston metatiedot. Koordinaatit voi muuntaa paremmin ihmisluettavaan tekstimuotoon seuraavalla hakulausekkeella: + +::: code-box +``` sql +SELECT +kunta_ni1, maaku_ni1, ST_AsText(wkb_geometry) +FROM +nlsfi.hallintoalue +WHERE +kunta_ni1 = 'Hanko'; +``` +::: + +## Harjoitus 4.3: Funktiot + +Kokeile myös seuraavia funktioita Hangon kunnan geometriatietoihin liittyen: + +- ST_Boundary + +::: code-box +``` sql +SELECT +... +FROM +... +WHERE +...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +SELECT +kunta_ni1, maaku_ni1, ST_Boundary() -- valitse funktioon geometria- sarake +FROM +skeema.taulu +WHERE +...; -- valitse Hangon kunta nimen perusteella. +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +kunta_ni1, maaku_ni1, ST_Boundary(wkb_geometry) +FROM +nlsfi.hallintoalue +WHERE +kunta_ni1 = 'Hanko'; +``` +::: +::: + +- ST_Centroid + +::: code-box +``` sql +SELECT +... +FROM +... +WHERE +...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +kunta_ni1, maaku_ni1, ST_Centroid() -- valitse funktioon geometria- sarake +FROM +skeema.taulu +WHERE +...; -- valitse Hangon kunta nimen perusteella. +``` +::: +::: + + + + +::: hidden-box +::: code-box +``` sql +SELECT +kunta_ni1, maaku_ni1, ST_Centroid(wkb_geometry) +FROM +nlsfi.hallintoalue +WHERE +kunta_ni1 = 'Hanko'; +``` +::: +::: + +- ST_Envelope + +::: code-box +``` sql +SELECT +... +FROM +... +WHERE +...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +kunta_ni1, maaku_ni1, ST_Envelope() -- valitse funktioon geometria- sarake +FROM +skeema.taulu +WHERE +...; -- valitse Hangon kunta nimen perusteella. +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +kunta_ni1, maaku_ni1, ST_Envelope(wkb_geometry) +FROM +nlsfi.hallintoalue +WHERE +kunta_ni1 = 'Hanko'; +``` +::: +::: + +Huomaa, miten vastauksena tuleva geometrian tyyppi vaihtelee eri funktioiden kohdalla. + +## Harjoitus 4.4: Spatiaaliset indeksit + +Tarkastele nlsfi.hallintoalue-taulun indeksejä. + +- Mitä indeksiä taululle on muodostunut? + +Indeksejä voi tarkastella sekä **pgAdmin**in tai QGIS **DB Manager**in avulla että luomalla tarkoitukseen sopivan SQL-kyselyn. + +Spatiaaliset indeksit on luotu silloin kun latasit aineistot QGISillä tietokantaan. Jos silloin valitsit, että indeksiä ei luoda niin indeksejä ei ole. Jos haluat luoda niitä jälkikäteen niin se onnistuu seuraavalla tavalla (esimerkki ainoastaan tieviiva-tasolle): + +::: code-box +``` sql +CREATE INDEX tieviiva_wkb_geometry +ON nlsfi.tieviiva +USING GIST(wkb_geometry); +``` +::: + +pgAdminissa löydät indeksit valitsemalla Schemas \> [valitse skeema] \> Tables \> [valitse taulu] \> Indexes. + +Jos käytät psql-komentoriviohjelmaa, voit tarkastella kaikki nlsfi-skeeman indeksejä seuraavalla psql-komennolla (huomaa että *-symboli löytää kaiken, mutta jos haluat tarkastella vain tiettyä indeksiä niin voit kirjoittaa sen *-symbolin tilalle): + +::: commandline-box +``` +\di+ nlsfi.* +``` +::: + +Yllä olevalla komennolla voit nähdä kaikki nlsfi-skeeman indeksit lisätietoineen. Psql:n \d-komento tulee sanasta describe ja lisäämällä i-kirjain niin se kertoo ainoastaan indekseistä. Plussa taas antaa enemmän tietoja kuin pelkkä \di. Voit kokeilla seuraavia komentoja ja vertailla ne aiempaan: + +::: commandline-box +``` +\d nlsfi.* +\di nlsfi.* + +``` +::: + +Mikä on tieviivoja sisältävän taulun koko ja miten suuri on siihen tehty indeksi? \ No newline at end of file diff --git a/src/GS009/05_harjoitus_5.Rmd b/src/GS009/05_harjoitus_5.Rmd new file mode 100644 index 00000000..c80f5701 --- /dev/null +++ b/src/GS009/05_harjoitus_5.Rmd @@ -0,0 +1,486 @@ +# Harjoitus 5: Paikkatietokohteiden geometria + +**Harjoituksen sisältö** - Harjoituksessa tutustutaan PostGISin tapaan käsitellä geometrioita. + +**Harjoituksen tavoite** - Harjoituksen jälkeen opiskelija tuntee PostGIS-geometrioiden käsittelyn perusteet. + +### Valmistautuminen + +Avaa [pgAdmin](/pgadmin) selaimeen ja kirjaudu sisään. Avaa **Query Tool** (Valitse _trainingdatabase_ **->** Ylhäältä **Tools** **->** **Query Tool**). + +## Harjoitus 5.1 + +Luodaan aluksi tietokantaan uusi taulu, johon muodostetaan erilaisia geometrioita: + +:::code-box +```sql +DROP TABLE IF EXISTS geom_test; + +CREATE TABLE IF NOT EXISTS geom_test +( + gid serial PRIMARY KEY, + name varchar(50), + geom geometry(geometry, 3067) +); +``` +::: + +Lisää sen jälkeen tauluun yksittäinen piste seuraavalla komennolla: + +:::code-box +```sql +INSERT INTO +geom_test(name, geom) +VALUES +('Single point', 'SRID=3067; POINT(0 0)'); +``` +::: + +Voit tarkastella taulun tietoja SQL-kyselyllä tai QGIS-ohjelmiston avulla: + +:::code-box +```sql +SELECT +name, ST_AsText(geom), ST_GeometryType(geom) +FROM +geom_test; +``` +::: + +## Harjoitus 5.2 + +Lisää vielä tauluun viiva ja monikulmio. + +Voit käyttää joko WKT-formaattia (LINESTRING(0 1, 2 3) ja POLYGON((4 5, 6 7, 8 9, 10 11, 4 5)), tai PostGIS:n funktioita ST_MakeLine, ST_MakePolygon ja ST_MakeEnvelope. + +Tarkista PostGISin ohjekirjasta funktioiden oikeat muodot: [8.4 Geometry Constructors](http://postgis.net/docs/reference.html#Geometry_Constructors). + +WKT- formaatti: + +:::code-box +```sql +INSERT INTO + +VALUES + +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- viivageometria +INSERT INTO +geom_test(name, geom) +VALUES +(..., '...; ...'); -- täytä arvot. Ota mallia ylhäällä olevasta piste- esimerkistä. + +-- polygonigeometria (monikulmio, alue) +INSERT INTO +geom_test(name, geom) +VALUES +(..., '...; ...'); -- täytä arvot. Ota mallia ylhäällä olevasta piste- esimerkistä. + +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +INSERT INTO +geom_test(name, geom) +VALUES +('Single linestring', 'SRID=3067; LINESTRING(0 1, 2 3)'); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single polygon', 'SRID=3067; POLYGON((4 5, 6 7, 8 9, 10 11, 4 5))'); +``` +::: +::: + +PostGIS- funktiolla: + +:::code-box +```sql +INSERT INTO + +VALUES + +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Tarkista dokumentaatiosta, miten funktioita käytetään ja täydennä arvot. +INSERT INTO +geom_test(name,geom) +VALUES +('Simple polygon using ST_MakeEnvelope', ST_MakeEnvelope()); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single point using ST_MakePoint', ST_SetSRID(ST_MakePoint(),3067)); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single linestring using ST_MakeLine', + ST_SetSRID(ST_MakeLine(ST_MakePoint(),ST_MakePoint()),3067)); +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +INSERT INTO +geom_test(name,geom) +VALUES +('Simple polygon using ST_MakeEnvelope', ST_MakeEnvelope(20,20,40,40,3067)); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single point using ST_MakePoint', ST_SetSRID(ST_MakePoint(100,200),3067)); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single linestring using ST_MakeLine', + ST_SetSRID(ST_MakeLine(ST_MakePoint(1,1),ST_MakePoint(50,50)),3067)); +``` +::: +::: + +### Pinta-alat +Geometrioihin liittyviä ominaisuuksia voidaan käyttää erilaisilla SQL-funktioilla. Seuraavalla hakulausekkeella haetaan Suomen pinta-alaltaan 10 pienintä kuntaa: + +:::code-box +```sql +SELECT +kunta_ni1 as "Nimi", ST_Area(wkb_geometry) as "Pinta-ala" +FROM +nlsfi.hallintoalue +ORDER BY +ST_Area(wkb_geometry) asc +LIMIT 10; +``` +::: + +Pinta-alat esitetään käytetyn koordinaattijärjestelmän yksiköissä, tässä neliömetreinä. Jos haluat pinta-alan hehtaareina, jaa alue 10 000:lla (100 m x 100 m). + +## Harjoitus 5.3 + +Mikä on Uudenmaan maakunnan viidenneksi pienimmän kunnan pinta-ala neliökilometreinä? Pyöristä käyttämällä **round()**-funktiota. + + +:::code-box +```sql +SELECT +... +FROM +... +WHERE +... +ORDER BY +... +LIMIT ... +OFFSET ...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- täydennä sarakkeet +-- round() funktio pyöristää arvon. Parametri '2' tarkoittaa, että luku +-- palautuu kahden desimaaliluvun tarkkuudella +SELECT +kunta_nimi_fi, maakunta +round((pinta_ala_funktio(geometria)/ ... ::numeric, 2) as "Pinta-ala (km2)" +-- selvitä, millä PostGIS- funktiolla voidaan laskea polygonin pinta-ala. +-- funktio palauttaa arvon koordinaattijärjestelmän yksiköissä, +-- tässä tapauksessa neliömetreinä. Yksikkö tulee muuntaa neliökilometreiksi +-- jakolaskulla. Täydennä oikea arvo. +FROM +nlsfi.hallintoalue +WHERE +maakunta = 'Uusimaa' +ORDER BY +pinta_ala_funktio(geometria) ... -- järjestä nousevaan järjestykseen +LIMIT 1 +OFFSET ...; +-- OFFSET- avainsana siirtää palautuvan tulosjoukon alkamaan tietueesta x. +-- Millä arvolla saat viidenneksi pienimmän kunnan? +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +kunta_ni1 as "Kunta", maaku_ni1 As "Maakunta", +round((ST_Area(wkb_geometry)/(1000*1000))::numeric,2) as "Pinta-ala (km2)" +FROM +nlsfi.hallintoalue +WHERE +maaku_ni1 = 'Uusimaa' +ORDER BY +ST_Area(wkb_geometry) asc +LIMIT 1 +OFFSET 4; +``` +::: +::: + +### Topologia + +Voimme tutkia paikkatietoaineistojen geometrioiden topologiaa monella eri tavalla, esimerkiksi luettelo suomalaisista kunnista, joissa on reikä: + +:::code-box +```sql +SELECT +kunta_ni1 as "Nimi" +FROM +nlsfi.hallintoalue +WHERE +ST_NumInteriorRings(ST_GeometryN(wkb_geometry,1)) > 0; +``` +::: + +### Pituus + +Paikkatietoaineistojen viivojen pituuksia voi tutkia **ST_Length**-funktiolla, harjoitusaineistossa olevien rautateiden yhteispituus: + +:::code-box +```sql +SELECT +sum(ST_Length(wkb_geometry))/1000 as "Rautateiden yhteenlaskettu pituus" +FROM +nlsfi.rautatieviiva; +``` +::: + +## Harjoitus 5.4 + +Mikä on suomalaisen tien nro 66 kokonaispituus? + +:::code-box +```sql +SELECT +... +FROM +... +WHERE +...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Millä PostGIS- funktiolla saat laskettua pituuden? +-- käytä SUM- funktiota laskemaan tietueiden kokonaispituus +SELECT +round(SUM(pituus_funktio(wkb_geometry))::numeric,2) as "Reitin 66 kokonaispituus (m)" +FROM +nlsfi.tieviiva +WHERE +...; -- valitse tietueet tienumeron mukaan +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +round(SUM(ST_Length(wkb_geometry))::numeric,2) as "Reitin 66 kokonaispituus (m)" +FROM +nlsfi.tieviiva +WHERE +tienumero = 66; +``` +::: +::: + +### Esitysmuodot + +Aikaisemmin katsoimme jo geometrioita tekstimuotoisena. PostGIS sisältää myös muita esitystapoja: + +:::code-box +```sql +SELECT +ST_asGeoJSON(wkb_geometry) +FROM +nlsfi.hallintoalue +WHERE +kunta_ni1 = 'Ilomantsi'; +``` +::: + +Kokeile eri tiedostomuotoja: + +- GML +- SVG +- KML +- X3D +- EWKB, EWKT + +### Eri tieluokkien pituudet + +Käytössä olevan aineiston tieluokittainen kokonaispituus: + +:::code-box +```sql +SELECT +tieluokka as "Tieluokka", sum(st_length(wkb_geometry))/1000 as "Kokonaispituus" +FROM +nlsfi.tieviiva +GROUP BY +tieluokka +ORDER BY +"Kokonaispituus" desc; +``` +::: + +### Tietotyyppien muutokset + +PostgreSQL sisältää kaksi tapaa tietotyyppien muutoksiin (casting): + +:::code-box +```mysql +cast(varchar_col AS int) -- SQL yhteensopiva +varchar_col::int -- PostgreSQLn perinteinen tapa +``` +::: + +:::code-box +```sql +SELECT CAST('POINT(0 0)' as geometry); +SELECT 'POINT(0 0)'::geometry; +``` +::: + + +## Harjoitus 5.5 + +Muodosta ensimmäisen harjoituksen lentokenttiä kuvaavasta tiedosta uusi paikkatietotaso, jossa lentokenttien sijainti ilmoitetaan PostGIS:n geometria-tyyppinä. + +Alla näkyvästä SQL-komennosta kannattaa ottaa vähän vinkkiä (myös sen suhteen, että kannattaa tarkastella vain pientä otosta lentokenttä-aineistosta): + + +:::code-box +```sql +SELECT name, longitude, latitude, 'POINT(' || longitude || ' '|| latitude || ')' as WKT_uudet +FROM airports +ORDER BY name +LIMIT 10; +``` +::: + +:::code-box +```sql +DROP TABLE IF EXISTS airports_geom + +CREATE TABLE airports_geom AS +( + SELECT + ... + FROM + ... +); + +SELECT +... +FROM +... +ORDER BY +... +LIMIT ...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Millä PostGIS- funktiolla voit määrittää koordinaattijärjestelmän? +DROP TABLE IF EXISTS airports_geom; + +CREATE TABLE airports_geom AS +( + SELECT + *, aseta_koordinaattijärjestelmä(CAST('...' as geometry),4326) as geometry + FROM + airports +); +-- täydennä funktio CAST() oikein. Katso ylhäältä mallia. + +-- tarkastele uutta taulua: + +SELECT +name, longitude, latitude, geom +FROM +airports_geom +ORDER BY +name +LIMIT 10; +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql + +DROP TABLE IF EXISTS airports_geom; + +CREATE TABLE airports_geom AS +( + SELECT + *, ST_SetSRID(CAST('POINT(' || longitude || ' '|| latitude || ')' as geometry),4326) as geometry + FROM + airports +); + + +-- tarkastele uutta taulua: + +SELECT +name, longitude, latitude, geometry +FROM +airports_geom +ORDER BY +name +LIMIT 10; +``` +::: +::: + +Jos valitset kaikki tason kentät, niin huomaat, että myös edellisen harjoituksen geometria-kenttä (geom) on mukana tasossa. Harvoin on tarpeen olla kaksi erillistä geometria-kenttää, mutta se on mahdollista PostGISissa. Harkitse vielä geometrian esitystapaa: geometry vai geography? Mistä sen saa selville? \ No newline at end of file diff --git a/src/GS009/06_harjoitus_6.Rmd b/src/GS009/06_harjoitus_6.Rmd new file mode 100644 index 00000000..1cb3f5c1 --- /dev/null +++ b/src/GS009/06_harjoitus_6.Rmd @@ -0,0 +1,418 @@ +# Harjoitus 6: Spatiaaliset relaatiot + +**Harjoituksen sisältö** - Harjoitellaan PostGISin spatiaalisiin relaatioihin liittyvien funktioiden käyttöä. + +**Harjoituksen tavoite** - Harjoituksen jälkeen opiskelija tuntee PostGISin spatiaalisen relaatioihin liittyvät funktiot ja osaa niiden avulla tehdä yksinkertaisia analyysejä. + +### Valmistautuminen + +Avaa [pgAdmin](/pgadmin) selaimeen ja kirjaudu sisään. Avaa **Query Tool** (Valitse _trainingdatabase_ **->** Ylhäältä **Tools** **->** **Query Tool**). + +### Käytettäviä funktioita + +Tässä harjoituksessa hyödynnetään ainakin näitä funktioita: + +| PostGIS-funktio | Toiminta | +|:--: | :---: | +| ST_Contains(geometry A, geometry B) | Palauttaa "TOSI", jos A sisältää B:n | +| ST_Crosses(geometry A, geometry B) | Palauttaa "TOSI", jos A leikkaa B:tä | +| ST_Disjoint(geometry A , geometry B) | Palauttaa "TOSI", jos geometriat eivät leikkaa toisiaan | +| ST_Distance(geometry A, geometry B) | Palauttaa geometrioiden välisen minimietäisyyden | +| ST_DWithin(geometry A, geometry B, radius) | Palauttaa "TOSI", jos A on lähempänä B:tä kuin annettua etäisyyttä | +| ST_Equals(geometry A, geometry B) | Palauttaa "TOSI", jos A on sama kuin B | +| ST_Intersects(geometry A, geometry B) | Palauttaa "TOSI", jos A leikkaa B:tä | +| ST_Overlaps(geometry A, geometry B) | Palauttaa "TOSI", jos A ja B ovat päällekkäin, mutteivät kuitenkaan toistensa sisäpuolella | +| ST_Touches(geometry A, geometry B) | Palauttaa "TOSI", jos A:n reuna koskettaa B:tä | +| ST_Within(geometry A, geometry B) | Palauttaa "TOSI", jos A on B:n sisäpuolella | + +## Harjoitus 6.1 + +Etsitään ne kunnat, joissa on lentokenttä: + +:::code-box +```sql +SELECT +a.kunta_ni1 +FROM +nlsfi.hallintoalue a, nlsfi.lentokenttapiste b +WHERE +ST_Contains(a.wkb_geometry, b.wkb_geometry); +``` +::: + +Huomaa kuinka kirjaimia a ja b käytetään kyselyssä aliaksina, eli sarakkeiden korvaavina niminä. Aliasten käyttö helpottaa varsinkin pitkien kyselyiden tulkitsemista ja kirjoittamista. Voit lukea lisää aliaksista esimerkiksi täältä: [postgresql-alias](https://www.postgresqltutorial.com/postgresql-alias/). + +Montako lentokenttää Suomessa on? + +:::code-box +```sql +SELECT +... +FROM +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Millä funktiolla voit laskea tietueiden määrän? +SELECT +funktio(id) +FROM +nlsfi.taulu; +-- Täydennä oikea taulu +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +count(id) +FROM +nlsfi.lentokenttapiste; +``` +::: +::: + +Jos lisäät SELECT-komentoon parametrin DISTINCT, saat selville kuinka monta lentokentällistä kuntaa Suomessa on. + +:::code-box +```sql +SELECT + +FROM +(SELECT DISTINCT + +FROM + +WHERE +ST_Contains(..., ...)); +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- käytä sisäkkäistä kyselyä +-- sisäkkäiselle kyselyllä annetaan alias +SELECT +funktio(kunta_distinct) +FROM +(SELECT DISTINCT +a.kunta_ni1 as kunta_distinct +FROM +nlsfi.hallintoalue a, nlsfi.lentokenttapiste b +WHERE +sisältää(... , ... )) as ...; +-- Millä PostGIS- funktiolla voit tarkastaa onko geometria b geometrian a sisällä? +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +count(kunta_distinct) +FROM +(SELECT DISTINCT +a.kunta_ni1 as kunta_distinct +FROM +nlsfi.hallintoalue a, nlsfi.lentokenttapiste b +WHERE +ST_Contains(a.wkb_geometry, b.wkb_geometry)) as DistinctKunta; +``` +::: +::: + +## Harjoitus 6.2 + +Missä Suomen kunnissa on kaksi lentokenttää? + +:::code-box +```sql +SELECT ... +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Vaihtoehto 1 +-- Käytä CTE:tä +WITH apm AS ( +SELECT DISTINCT +a.kunta_ni1, COUNT(...) OVER(PARTITION BY ...) AS CountAirports +FROM +nlsfi.hallintoalue a, nlsfi.lentokenttapiste b +WHERE +sisältää(a.wkb_geometry, b.wkb_geometry) +ORDER BY +CountAirports DESC +) + +-- tarkastele tuloksia: + +SELECT +kunta_ni1 as "Municipality", countairports AS "Count of Airports" +FROM +apm +WHERE +CountAirports = 2; +``` +::: + +:::code-box +```sql +-- Vaihtoehto 2 +SELECT +a.kunta_ni1 as "Kunta", count(...) as "Lkm" +FROM +nlsfi.hallintoalue a, nlsfi.lentokenttapiste b +WHERE +sisältää(a.wkb_geometry, b.wkb_geometry) +GROUP BY +a.kunta_ni1 +HAVING count(...) = ...; + +-- täydennä tyhjät kohdat. Valitse oikea PostGIS- funktio +``` +::: +::: + +Perusteellinen ratkaisuvaihtoehto: + + + +:::hidden-box +:::code-box +```sql +WITH apm AS ( +SELECT DISTINCT +a.kunta_ni1, COUNT(a.kunta_ni1) OVER(PARTITION BY a.kunta_ni1) AS CountAirports +FROM +nlsfi.hallintoalue a, nlsfi.lentokenttapiste b +WHERE +ST_Contains(a.wkb_geometry, b.wkb_geometry) +ORDER BY +CountAirports DESC +) + +SELECT +kunta_ni1 as "Municipality", countairports AS "Count of Airports" +FROM +apm +WHERE +CountAirports = 2; +``` +::: +::: + +Pelkistetympi ratkaisuvaihtoehto: + + + +:::hidden-box +:::code-box +```sql +SELECT +a.kunta_ni1 as "Kunta", count(*) as "Lkm" +FROM +nlsfi.hallintoalue a, nlsfi.lentokenttapiste b +WHERE +ST_Contains(a.wkb_geometry, b.wkb_geometry) +GROUP BY +a.kunta_ni1 +HAVING count(*) = 2; +``` +::: +::: + +Suorita ao. SQL-lause. Mitä sillä saadaan selville? + +:::code-box +```sql +SELECT +ST_ASText(a.wkb_geometry), a.id +FROM +nlsfi.lentokenttapiste a, nlsfi.lentokenttapiste b +WHERE +ST_Equals(a.wkb_geometry,b.wkb_geometry) AND a.id <> b.id; +``` +::: + + + +:::hidden-box +SQL- kysely palauttaa ne tietueet, joiden geometria on identtinen, mutta id eri. +::: + +## Harjoitus 6.3 +Etsitään ne kunnat, joissa ei ole rautatietä: + +:::code-box +```sql +SELECT +b.kunta_ni1 +FROM +(SELECT + ST_union(wkb_geometry) as wkb_geometry + FROM + nlsfi.rautatieviiva) as a, nlsfi.hallintoalue b +WHERE +ST_Disjoint(a.wkb_geometry, b.wkb_geometry); +``` +::: +## Harjoitus 6.4 +Etsitään kolme lähintä lentokenttää. + +K Nearest Neighbours -menetelmällä (KNN) voidaan hakea kolme lähimpänä jonkin kunnan keskustaa sijaitsevaa lentokenttää. + +:::code-box +```sql +WITH forssa AS +(SELECT + wkb_geometry + FROM + nlsfi.hallintoalue + WHERE + kunta_ni1 = 'Forssa') + +SELECT +*, round(ST_Distance(forssa.wkb_geometry, a.wkb_geometry)/1000) as "km" +FROM +nlsfi.lentokenttapiste a, forssa +ORDER BY +forssa.wkb_geometry <-> a.wkb_geometry +LIMIT 3; +``` +::: + +Sama ongelma voidaan ratkaista myös ilman KNN-algoritmia: + +:::code-box +```sql +SELECT +*, round(ST_Distance(wkb_geometry,( + SELECT ST_Centroid(wkb_geometry) + FROM + nlsfi.hallintoalue + WHERE + kunta_ni1 ='Forssa'))/1000) as etaisyys +FROM +nlsfi.lentokenttapiste +ORDER by +etaisyys +LIMIT 3; +``` +::: + +Miksi saadut tulokset poikkeavat toisistaan? + +## Harjoitus 6.5 +Mitkä ovat Kuopion naapurikunnat? + +:::code-box +```sql +SELECT +b.kunta_ni1 +FROM +(SELECT + kunta_ni1, wkb_geometry + FROM + nlsfi.hallintoalue + WHERE + kunta_ni1 = 'Kuopio') a, nlsfi.hallintoalue b +WHERE +ST_Touches(a.wkb_geometry, b.wkb_geometry); +``` +::: + +## Harjoitus 6.6 +Etsitään ne tieviivat, jotka leikkaavat kuntarajoja: + +:::code-box +```sql +SELECT +a.tienumero, a.wkb_geometry +FROM +nlsfi.tieviiva a, nlsfi.hallintoalue b +WHERE +ST_Crosses(a.wkb_geometry, b.wkb_geometry); +``` +::: + +Tulosten visualisoimiseksi, voit muodostaa **uuden skeeman** (tmp). Voit luoda uuden taulun, johon viet tuloksen. Visualisointiin voit käyttää esimerkiksi QGIS-ohjelmistoa. Voit muodostaa tuloksesta myös näkymän (view), mutta muista kuitenkin lisätä mukaan **yksilöivä tunnus** (id) sekä myös **DISTINCT**, jotta yksilöivät tunnukset pysyvät yksilöivinä. + +:::code-box +```sql +CREATE SCHEMA IF NOT EXISTS tmp; +``` +::: + +:::code-box +```sql +DROP TABLE IF EXISTS tmp.crossroads; + +CREATE TABLE tmp.crossroads AS +( + SELECT + a.tienumero, a.wkb_geometry + FROM + nlsfi.tieviiva a, nlsfi.hallintoalue b + WHERE + ST_Crosses(a.wkb_geometry, b.wkb_geometry) +); +``` +::: + +:::code-box +```sql +DROP VIEW IF EXISTS tmp.view_crossroads; + +CREATE VIEW tmp.view_crossroads AS +( + SELECT DISTINCT + a.tienumero, a.wkb_geometry, a.id + FROM + nlsfi.tieviiva a, nlsfi.hallintoalue b + WHERE + ST_Crosses(a.wkb_geometry, b.wkb_geometry) +); +``` +::: + +Kumman luominen oli nopeampaa: taulun vai näkymän? + +:::hint-box +Entä käyttö QGISissä? Miksi? +::: + +## Harjoitus 6.7 +Lasketaan minimietäisyydet lentoasemilta lähimmälle rautatielle: + +:::code-box +```sql +SELECT +a.id, MIN(ST_Distance(a.wkb_geometry, b.wkb_geometry)) as "dist" +FROM +nlsfi.lentokenttapiste a, nlsfi.rautatieviiva b +GROUP BY +a.id +ORDER BY +dist; +``` +::: \ No newline at end of file diff --git a/src/GS009/07_harjoitus_7.Rmd b/src/GS009/07_harjoitus_7.Rmd new file mode 100644 index 00000000..99fb9d7c --- /dev/null +++ b/src/GS009/07_harjoitus_7.Rmd @@ -0,0 +1,285 @@ +# Harjoitus 7: Koordinaattijärjestelmät + +**Harjoituksen sisältö** - Harjoituksessa tutustutaan PostGISin tapaan käsitellä koordinaattijärjestelmiä ja karttaprojektioita. + +**Harjoituksen tavoite** - Harjoitusten jälkeen opiskelijalla on perustiedot PostGISin koordinaattijärjestelmien ja karttaprojektion käytöstä. + +### Valmistautuminen + +Avaa [pgAdmin](/pgadmin) selaimeen ja kirjaudu sisään. Avaa **Query Tool** (Valitse _trainingdatabase_ **->** Ylhäältä **Tools** **->** **Query Tool**). Käytössä tulee olla myös web-selain, joka mahdollistaa pääsyn Maanmittauslaitoksen koordinaattien muunnospalveluun. + +### Käytettäviä funktioita + +Tässä harjoituksessa koordinaattien konversioihin ja muunnoksiin voidaan käyttää mm. seuraavia funktioita: + +| PostGIS-funktio | Toiminta | +|:--: | :---: | +| ST_GeomFromText(text WKT, integer srid) | Palauttaa ST_Geometry-olion WKT-muotoisesta esitystavasta annetulla EPSG:llä | +| ST_AsText(geometry g) | Palauttaa ST_Geometry-olion määrityksen selväkielisessä WKT-muodossa | +| ST_Transform(geometry g1, integer srid) | Palauttaa geometrian muunnettuna parametrina annetun EPSG:n mukaiseen koordinaattijärjestelmään | +| ST_Transform(geometry geom, text to_proj) | Palauttaa geometrian muunnettuna parametrina PROJ.4-muodossa annettuun järjestelmään | +| ST_Transform(geometry geom, text from_proj, text to_proj) | Palauttaa geometrian muunnettuna PROJ.4-muodossa annetuista järjestelmistä toiseen | +| ST_Transform(geometry geom, text from_proj, integer to_srid) | Palauttaa geometrian muunnettuna PROJ.4-muodossa annetusta järjestelmästä annetun EPSG:n mukaiseen koordinaattijärjestelmään | + +## Harjoitus 7.1: Koordinaattipisteen konversio + +Muodosta maantieteellisistä ETRS89-koordinaateista (EPSG:4258) 24.3953148 (pituusaste) ja 60.2174696 (leveysaste) Kallion kirkkoa vastaava PostGISin koordinaattipiste: + +:::code-box +```sql +SELECT +ST_GeomFromText('POINT(24.3953148 60.2174696)', 4258); +``` +::: + +## Harjoitus 7.2: Koordinaattimuunnos + +Tee Kallion kirkon koordinaatteille konversio ETRS-TM35FIN-koordinaattijärjestelmään (EPSG:3067) hyödyntämällä **ST_Transform**-funktiota. + +:::code-box +```sql +SELECT +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- täydennä oikeat funktiot vinkkien perusteella. +-- täydennä lähto- ja tavoitekoordinaattijärjestelmät '...'- kohtiin +SELECT +geometria_tekstinä(koordinaattimuunnos(luo_geometria_tekstistä('POINT(24.3953148 60.2174696)', ...), ...)); +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +ST_asText(ST_Transform(ST_GeomFromText('POINT(24.3953148 60.2174696)', 4258), 3067)); +``` +::: +::: + +Tuloksena pitäisi tulla seuraavat koordinaattipisteet EPSG:3067-koordinaattijärjestelmässä: + +:::code-box +``` +0101000020FB0B0000BE87BABAC1B515411865678EF3795941 +``` +::: +tai selväkielisemmin: + +:::code-box +``` +POINT(355696.43235218147 6678478.225060724) +``` +::: + +## Harjoitus 7.3: Koordinaattimuunnosten vertailu + +Tee seuraavaksi Kallion kirkon koordinaateille muunnos **KKJ2**-koordinaattijärjestelmään (EPSG:2392). + +:::code-box +```sql +SELECT +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- täydennä oikeat funktiot vinkkien perusteella. +-- täydennä lähto- ja tavoitekoordinaattijärjestelmät '...'- kohtiin +SELECT +geometria_tekstinä(koordinaattimuunnos(luo_geometria_tekstistä('POINT(24.3953148 60.2174696)', ...), ...)); +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +ST_asText(ST_Transform(ST_GeomFromText('POINT(24.3953148 60.2174696)', 4258), 2392)); +``` +::: +::: + +Tuloksen pitäisi olla: + +:::code-box +``` +POINT(6678507.76432921 2522091.992364572) +``` +::: + +Suomessa yleisin koordinaattijärjestelmä lienee **ETRS-TM35FIN** (epsg:3067), joka kattaa koko Suomen. Kunta- ja aluekohtaisesti käytössä on eri GK-kaistat **ETRS-GK19** - **ETRS-GK31**. Laajempi lista koordinaattijärjestelmistä Suomesta löydät [Maanmittauslaitoksen sivuilta](https://www.maanmittauslaitos.fi/kartat-ja-paikkatieto/koordinaatit-ja-paikannus/epsg-koodit-ja-proj-muunnosohjelma). + +Välillä pitää tehdä muunnoksia koordinaattijärjestelmien välillä. Silloin kannattaa aina tarkistaa koordinaatit jälkikäteen. Koordinaattiarvojen muunnoksia voi silmämääräisen tarkastuksen lisäksi tehdä myös Maanmittauslaitoksen ylläpitämän [koordinaattimuunnospalvelulla](https://kartta.paikkatietoikkuna.fi/) Paikkatietoikkunassa. Koordinaattimuunnostoiminto löytyy **Paikkatietoikkunan** vasemman reunan valikosta nimellä **Koordinaattimuunnos**. + +![](img/paikkatietoikkuna.png) + +### Koordinaattijärjestelmien määritykset + +Koordinaattijärjestelmien kuvaukset löytyvät **spatial_ref_sys**–taulusta: + + +:::code-box +```sql +SELECT +srid, proj4text +FROM +spatial_ref_sys +WHERE +srid = 2392; +``` +::: + +Tallennetut muunnosparametrit EUREF-FIN-datumin ja KKJ-datumin välillä antavat maksimissaan kahden metrin virheen Suomen alueella (kuva JHS 197-suosituksesta): + +![](img/JHSsuositus.png) + +#### Puuttuvia koordinaattijärjestelmiä + +EUREF-FIN -pohjaisten koordinaattijärjestelmien käyttöönotossa on EPSG-tietokantaan tuotettu erilaisia versioita ns. GK-koordinaattijärjestelmistä. + +## Harjoitus 7.4: Koordinaattijärjestelmien määrittelyt + +Tarkista mitkä määrittelyt koulutuksessa käytettävässä tietokannassa on ETRS-GK24FIN -koordinaattijärjestelmälle. + +Tutki ensin spatial_ref_sys-taulun kenttiä. Päättele mistä kentästä voi löytyä tiedot koordinaattijärjestelmän tiedoista. Käytä LIKE-operaattoria. + +:::code-box +```sql +SELECT ... +FROM +... +WHERE +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +SELECT * +FROM +spatial_ref_sys +WHERE +"srtext" LIKE '...'; +-- täydennä '...' kohtaan arvo siten, että kysely palauttaa +-- ETRS-GK24FIN- koordinaattijärjestelmän määritelmän. +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT * +FROM +spatial_ref_sys +WHERE +"srtext" LIKE '%ETRS-GK24FIN%'; +``` +::: +::: + +## Harjoitus 7.5: Koordinaattijärjestelmien vertailu + +Mitä eroja on EPSG:3132- ja EPSG:3879-koordinaattijärjestelmillä? + +:::code-box +```sql +SELECT +... +FROM +... +WHERE +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Missä sarakkeessa on EPSG- koodit? +SELECT +..., proj4text +FROM +spatial_ref_sys +WHERE +... in (3132, 3879); +-- Valitse EPSG-koodin perusteella +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +srid, proj4text +FROM +spatial_ref_sys +WHERE +srid in (3132, 3879); + +-- Huomaat vastauksessa yhden eron. Tämä liitty ns. valeitään (False Easting) joka eroaa koordinaattijärjeselmien välillä. +``` +::: +::: + +## Harjoitus 7.6: Uuden paikkatietotaulun luominen + +Luodaan tietokantaan uusi paikkatietotaulu, jossa on geometria-kenttä, jonka koordinaattijärjestelmä on WGS84. Luodaan tauluun neljä kenttää (gid, name, ICAO, geom): + +:::code-box +```sql +DROP TABLE IF EXISTS air_geom; + +CREATE TABLE air_geom +( + gid serial PRIMARY KEY, + name varchar(254), + ICAO varchar(254), + geom geometry(Point,4326) +); +``` +::: + +Luetaan airports-taulusta tiedot uuden taulun kenttiin. Muodostetaan ensin SELECT-lauseke, niin voidaan varmistua, että tietojen sisäänluku onnistuu. + +:::code-box +```sql +INSERT INTO +air_geom(geom, name, ICAO) +SELECT +ST_GeomFromText('POINT(' || airports.longitude|| ' ' || airports.latitude||')',4326), +airports.name, airports.icao_code +FROM +airports; +``` +::: + +Kahdella putkimerkillä ```||``` yhdistetään tekstiä. diff --git a/src/GS009/08_harjoitus_8.Rmd b/src/GS009/08_harjoitus_8.Rmd new file mode 100644 index 00000000..15cd49aa --- /dev/null +++ b/src/GS009/08_harjoitus_8.Rmd @@ -0,0 +1,309 @@ +# Harjoitus 8: Geoprosessointi + +**Harjoituksen sisältö** - Harjoituksessa tutustutaan PostGISin geoprosessointifunktioihin. + +**Harjoituksen tavoite** - Harjoituksen jälkeen opiskelija tuntee geoprosessointifunktioiden perusteet. + +### Valmistautuminen + +Avaa [pgAdmin](/pgadmin) selaimeen ja kirjaudu sisään. Avaa **Query Tool** (Valitse _trainingdatabase_ **->** Ylhäältä **Tools** **->** **Query Tool**). + +## Harjoitus 8.1: Keskipisteet + +Kirjoitetaan yhdessä **SQL-terminaaliin** seuraava komento: + +:::code-box +```sql +SELECT +ST_Centroid(wkb_geometry) as "Centroids of first 10" +FROM +nlsfi.hallintoalue +LIMIT 10; +``` +::: + +Komento tuottaa kymmenen ensimmäisen alueen keskipisteet. + +## Harjoitus 8.2: Keskipisteiden määritys + +Ovatko kaikki keskipisteet alueiden sisäpuolella? Kuinka monta pistettä jää ulkopuolelle? + +:::code-box +```sql +SELECT ... +``` +::: + +Huomaa, että saat selville vastauksen myös tulostamalla kaikkien sellaisten kuntien nimet, joiden keskipiste jää alueen ulkopuolelle ja laskemalla tulostaulukon rivien lukumäärän. + + + +::: hidden-box +:::code-box +```sql +-- vaihtoehto 1 ST_Contains- funktiolla +-- CTE:llä +WITH notin AS( + SELECT + ... + FROM + ... + WHERE + NOT ... + +SELECT +count(...) +FROM +notin; +``` +::: + +:::code-box +```sql +-- vaihtoehto 2 - ST_Within- funktiolla +SELECT +... +FROM +... +WHERE +NOT ...; +``` +::: +::: + +Ratkaisuvaihtoehto 1 (käytetään **ST_Contains**-funktiota): + + + +:::hidden-box +:::code-box +```sql +WITH notin AS( + SELECT + kunta_ni1 as "withST_Contains" + FROM + nlsfi.hallintoalue + WHERE + NOT ST_Contains(wkb_geometry, ST_Centroid(wkb_geometry))) + +SELECT +count(notin."withST_Contains") +FROM +notin; +``` +::: +::: + +Ratkaisuvaihtoehto 2 (käytetään **ST_Within**-funktiota): + + + +:::hidden-box +:::code-box +```sql +SELECT +kunta_ni1 as "with ST_Within" +FROM +nlsfi.hallintoalue +WHERE +NOT ST_Within(ST_Centroid(wkb_geometry), wkb_geometry); +``` +::: +::: + +## Harjoitus 8.3: Etäisyydet + +Miten paljon harjoituksessa 8.2 löydettyjen kuntien painokeskipisteet eroavat **ST_PointOnSurface**–funktion pisteistä? + +:::code-box +```sql +SELECT +... +FROM +... +WHERE +NOT ...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Millä PostGIS- funktiolla voit laskea etäisyyden pisteiden välillä? +SELECT +kunta_ni1 as "Kunta", +round(etäisyys(ST_PointOnSurface(wkb_geometry), ST_centroid(wkb_geometry))) +as "Distance PntOnSurface and Centroid" +FROM +nlsfi.hallintoalue +WHERE +NOT ...; +-- rajaa pois pisteet, jotka ei ole polygonin sisällä. +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +kunta_ni1 as "Kunta", +round(ST_Distance(ST_PointOnSurface(wkb_geometry), ST_centroid(wkb_geometry))) +as "Distance PntOnSurface and Centroid" +FROM +nlsfi.hallintoalue +WHERE +NOT ST_Within(ST_Centroid(wkb_geometry), wkb_geometry); +``` +::: +::: + +## Harjoitus 8.4: Vyöhykkeet + +Muodostetaan tiestölle vyöhyke: + +:::code-box +```sql +SELECT +id, ST_Buffer(wkb_geometry, 100) as geom +FROM +nlsfi.tieviiva +WHERE +tienumero = 66; +``` +::: + +Muodosta vyöhykkeestä näkymä ja visualisoi se QGISissä. Voit myös muodostaa useamman vyöhykkeen eri etäisyyksille. + +:::code-box +```sql +DROP VIEW IF EXISTS nlsfi.view_road_buffer; + +CREATE VIEW nlsfi.view_road_buffer AS ( + WITH buffers AS ( + ... + UNION + ... + ) + SELECT + row_number() OVER() AS vid, geom, buffer + FROM + buffers +); +``` +::: + + + +::: hidden-box +:::code-box +```sql +DROP VIEW IF EXISTS nlsfi.view_road_buffer; + +CREATE VIEW nlsfi.view_road_buffer AS ( + WITH buffers AS ( + SELECT + ..., 100 as buffer -- täydennä ST_Buffer funktio + FROM + nlsfi.tieviiva + WHERE + ... -- valitse tienumeron 66 mukaan + UNION + SELECT + ..., 250 as buffer -- täydennä ST_Buffer funktio + FROM + nlsfi.tieviiva + WHERE -- valitse tienumeron 66 mukaan + ... + ) + SELECT + row_number() OVER() AS vid, geom, buffer + FROM + buffers +); +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +DROP VIEW IF EXISTS nlsfi.view_road_buffer; + +CREATE VIEW nlsfi.view_road_buffer AS ( + WITH buffers AS ( + SELECT + ST_Buffer(wkb_geometry, 100) as geom, 100 as buffer + FROM + nlsfi.tieviiva + WHERE + tienumero = 66 + UNION + SELECT + ST_Buffer(wkb_geometry, 250) as geom, 250 as buffer + FROM + nlsfi.tieviiva + WHERE + tienumero = 66 + ) + SELECT + row_number() OVER() AS vid, geom, buffer + FROM + buffers +); +``` +::: +::: + +> Editoi alkuperäistä tieviivaa QGIS:ssä. + +## Harjoitus 8.5: Geometrioiden yhdistäminen + +Muodosta (yhdistä) hallintoalueista maakuntien raja -aineisto: + +:::code-box +```sql + +DROP TABLE IF EXISTS tmp.maakunnat; + +CREATE TABLE tmp.maakunnat as ( + SELECT + ST_Union(wkb_geometry), maaku_ni1 as "Maakunnan nimi" + FROM + nlsfi.hallintoalue + GROUP BY + maaku_ni1 +); +``` +::: + +Vastaavasti, aineiston voi muodostaa myös hyödyntämällä näkymiä: + +:::code-box +```sql +DROP VIEW IF EXISTS tmp.view_maakunta; + +CREATE VIEW tmp.view_maakunta AS ( + SELECT + ST_Union(wkb_geometry), maaku_ni1 + FROM + nlsfi.hallintoalue + GROUP BY + maaku_ni1 +); +``` +::: + +### PostGISin tehokkuus + +Yksi suurimmista hyödyistä PostGISin käytössä on sen tehokkuus suuria tietoaineistoja käsiteltäessä. + +#### Lisätehtävä + +Suurin osa geoprosessoinnin työkaluista löytyy myös QGISistä, mutta PostGISin tehokkuus tulee esille erityisesti, jos kokeilet tehdä saman operaation QGISin työkaluilla ja PostGISillä. Huomaatko eron? \ No newline at end of file diff --git a/src/GS009/09_harjoitus_09.Rmd b/src/GS009/09_harjoitus_09.Rmd new file mode 100644 index 00000000..d6d5887b --- /dev/null +++ b/src/GS009/09_harjoitus_09.Rmd @@ -0,0 +1,249 @@ +# Harjoitus 9: PostgreSQL:n ylläpito + +**Harjoituksen sisältö** - PostgreSQL:n ylläpitoon liittyviä aiheita. + +**Harjoituksen tavoite** - Opiskelija tuntee PostgreSQL:n ylläpitoon liittyviä perusasioita. + +### Valmistautuminen + +Avaa [pgAdmin](/pgadmin) selaimeen ja kirjaudu sisään. Avaa **Query Tool** (Valitse _trainingdatabase_ **->** Ylhäältä **Tools** **->** **Query Tool**). + +## Harjoitus 9.1: Taulutilat + +Tarkista koulutuspalvelimen oletustaulutilojen sijainti. Käyttäjien tiedot sijaitsevat **pg_default**-taulutilassa, joka on data_directoryn base-hakemistossa. Järjestelmän yleiset tiedot sijaitsevat **pg_global**-taulutilassa, joka on data_directoryn global-hakemistossa. Datahakemiston sijainnin voit tarkistaa komennolla: + +:::code-box +```sql +SHOW data_directory; +``` +::: + +## Harjoitus 9.2: Käyttäjäroolit + +Oletusarvoisesti PostgreSQL:ään luodaan postgres-niminen rooli ja samanniminen tietokanta. Aiemmin harjoituksissa on luotu koulutusta varten tietokanta (trainingdatabase). Voit luoda uuden käyttäjän tietokantapalvelimeen seuraavalla SQL-komennolla: + +:::code-box +```sql +DROP ROLE IF EXISTS matti; + +CREATE ROLE +matti +LOGIN PASSWORD +'1234' +CREATEDB +VALID UNTIL +'infinity'; +``` +::: + +**CREATEDB**-parametri määrittää roolille oikeudet tietokantojen luomiseen. VALID-parametri määrittää roolin voimassaolon ajan (tässä tapauksessa ikuisesti). + +Luo uusi ylläpitäjän rooli seuraavalla SQL-komennolla: + +:::code-box +```sql +DROP ROLE IF EXISTS dba; + +CREATE ROLE +dba +LOGIN PASSWORD +'1234' +SUPERUSER +VALID UNTIL +'2050-12-31 00:00'; +``` +::: + +Uudella roolilla on ylläpitäjän oikeudet (SUPERUSER) ja se on voimassa 1. tammikuuta 2024 asti. +Voit tarkastella käyttäjien tietoja pgAdminin puuhierarkian kohdassa **Login/Group Roles**. + +## Harjoitus 9.3: Ryhmäroolit + +Ryhmäroolit (group roles) luodaan seuraavalla SQL-komennolla: + +:::code-box +```sql +DROP ROLE IF EXISTS admins; + +CREATE ROLE +admins +INHERIT; +``` +::: + +INHERIT-parametri tarkoittaa sitä, että kaikki **our_admins**-ryhmän sisällä olevat roolit perivät ryhmän oikeudet. Poikkeuksena, **superuser**-oikeus ei koskaan periydy PostgreSQL:ssä. + +Lisää roolit matti ja dpa ryhmään admins seuraavasti: + +:::code-box +```sql +GRANT +admins +TO +matti, dba; +``` +::: + +Voit vaihtaa rooleja komennolla **SET ROLE**: + +:::code-box +```sql +SET ROLE +matti; +``` +::: + +Käytössä olevan roolin voi tarkistaa komennolla: + +::: code-box +```sql +SELECT current_user; +``` +::: + +Kokeile komentoa SELECT session_user. + +:::code-box +```sql +SELECT ... +``` +::: + +:::hint-box +Mikä on current_user ja session_user välinen ero? +::: + +## Harjoitus 9.4: Roolien lisääminen käyttöliittymässä + +![](img/pgadminrooli.png) + +Roolien hallinta on selkeämpää pgAdminin käyttöliittymässä. Lisää uusi käyttäjä, valitse salasana ja lisää hänet myös admins-ryhmärooliin, huomaa SQL-välilehdelle muodostuva SQL-lauseke. Roolien poistaminen tapahtuu **DROP ROLE < roolin nimi >** -komennolla. + +## Harjoitus 9.5: Uuden taulutilan luominen + +Uutta taulutilaa varten pitää luoda ensin palvelimelle kansio. Kansion tulee olla postgres-käyttäjän omistuksessa ja käyttöoikeudet vain postgres-käyttäjälle. Hakemisto on luotu valmiiksi palvelimelle komennoilla: + +``` +sudo mkdir /usr/local/tmp_tbls +sudo chown -R postgres:postgres /usr/local/tmp_tbls/ +sudo chmod 700 /usr/local/tmp_tbls/ +``` + +Luo uusi taulutila SQL-komennolla psql:n tai pgAdminin avulla: + +:::code-box +```sql +CREATE TABLESPACE tmp_tablespace +LOCATION '/usr/local/tmp_tbls'; +``` +::: + +## Harjoitus 9.6: Tietokannan ja taulun taulutilan muuttaminen + +Koko tietokannan taulutilan voi muuttaa yhdellä komennolla. + +:::hint-box +**HUOM!** Tätä ei kuitenkaan voi tehdä jos tietokantaan on auki aktiivisia yhteyksiä! +::: + +1. Sulje pgAdminin tietokantayhteys harjoitustietokantaasi klikkaamalla tietokantaa sivupaneelissa hiiren oikealla painikkeella ja valitsemalla **Disconnect Database**. +2. Avaa tämän jälkeen sivupaneelista postgres-tietokanta ja avaa **Query tool** (voit tehdä tämän myös psql:n avulla). Anna komento: + +:::code-box +```sql +ALTER DATABASE trainingdatabase +SET TABLESPACE tmp_tablespace; +``` +::: + +:::hint-box +Mikäli tämä ei onnistu, ja pgAdmin4 kertoo, että tietokantaan on aktiivisia yhteyksiä, yritä kirjautua ulos ja takaisin sisään pgAdminiin. +::: + + +Jos joki yhteys jää auki niin voit tarvittaessa sulkea kaikki muut yhteyder käyttmällä seuraavaa kyselyä: + +:::code-box +```sql +SELECT pg_terminate_backend(pid) +FROM pg_stat_activity +WHERE datname = 'trainingdatabase' + AND pid <> pg_backend_pid(); +``` +::: + +Voit tarkistaa tietokannan taulutilan sijainnin SQL-kyselyllä: + +:::code-box +```sql +SELECT +spcname, pg_tablespace_location(oid) +FROM +pg_tablespace; +``` +::: + +Huomaat, että taulutilan sijainnin kohdassa on tyhjää. Tämä tarkoittaa, että taulutila sijaitsee kotihakemistossa. + +Luo testausta varten tilapäinen taulu: + +:::code-box +```sql +DROP TABLE IF EXISTS tmp_table; + +CREATE TABLE tmp_table AS +SELECT x +FROM +generate_series(2,5000,2) AS x; +``` +::: + +Taulun käyttämän taulutilan voit tarkistaa seuraavalla komennolla: + +:::code-box +```sql +SELECT +tablename, tablespace +FROM +pg_tables +WHERE +tablename = 'tmp_table'; +``` +::: + +Muuta taulun taulutilaa seuraavalla komennolla: + +:::code-box +```sql +ALTER TABLE +tmp_table +SET TABLESPACE +tmp_tablespace; +``` +::: + +Tarkista, että taulun taulutila on nyt muuttunut. Voit myös käyttää pgAdminin käyttöliittymää taulutilojen tarkastamiseen. + +## Harjoitus 9.7: Indeksin taulutilan muuttaminen + +Voit luoda indeksin tauluun komennolla: + +:::code-box +```sql +CREATE INDEX +idx_tmp_x +ON tmp_table(x); +``` +::: + +Indeksit luodaan oletusarvoisesti **pg_default**-taulutilaan. Usein käytetyt indeksit voi olla tarpeen tallentaa sellaiseen taulutilaan, joka käyttää palvelimessa olevaa nopeinta levyä (esimerkiksi SSD-levyt). Indeksien taulutilan muuttaminen onnistuu seuraavasti: + +:::code-box +```sql +ALTER INDEX +idx_tmp_x +SET TABLESPACE +tmp_tablespace; +``` +::: + diff --git a/src/GS009/10_harjoitus_10.Rmd b/src/GS009/10_harjoitus_10.Rmd new file mode 100644 index 00000000..ff9fd785 --- /dev/null +++ b/src/GS009/10_harjoitus_10.Rmd @@ -0,0 +1,42 @@ +# Harjoitus 10: Varmistus ja palautus + +**Harjoituksen sisältö** - Tutustutaan tietokannan varmistamiseen ja palautukseen. + +**Harjoituksen tavoite** - Opiskelija tietää kuinka tietokanta voidaan varmistaa ja palauttaa. + +## Harjoitus 10.1: Luodaan varmistus + +Tehdään varmistus koulutuskannasta pgAdmin-työkalun avulla. Valitse harjoitustietokanta ja valitse hiiren oikealla painikkeella **Backup...**-toiminto:
+ + +![](img/pgadminback.png) + +:::hint-box +Mikäli Backup-ikkuna ei avaudu vaan törmäät virheilmoitukseen, menettele seuraavasti: File > Preferences > vasemman reunan valikosta Paths alta Binary Paths ja kirjoita PostgreSQL Binary Path -kenttään **/usr/bin** +::: + +Täytä avautuvaan **Backup**-ikkunaan tiedoston nimeksi **"trainingdatabase_backup"**, formaatiksi **Tar** ja koodaukseksi **UTF8**. + +![](img/pgadminback2.png) + +## Harjoitus 10.2: Tehdään palautus + +### Luo uusi tietokanta + +Klikkaa hiiren oikeaa nappia tietokantaklusterin päällä ja valitse **Create > Database…**. Anna tietokannalle nimeksi **"trainingdatabase2"**. + +![](img/pgadmindb2.png) + +### Palauta varmistustiedostosta tiedot + +Palautetaan siihen varmistukset klikkaamalla hiiren oikeaa painiketta juuri luodun **trainingdatabase2**-tietokannan päällä. Valitse **Restore... > Filename > …** ja hae äsken tallentamasi .tar-tiedosto koulutustietokoneesta. + +![](img/pgadminrestore.png) + +Jos varmistustiedostoa ei meinaa löytyä, valitse **Select file** -ikkunan oikean alanurkan **Format**-alasvetovalikosta formaatiksi **All Files**. Voit tarkastella palautettavia kohteita ennen palautusta **Display Objects** -toiminnon avulla. + +![](img/pgadmindisplay.png) + +:::hint-box +Kuinka kopioit harjoitustietokannan rakenteen (skeeman) toiseen tietokantaan? +::: \ No newline at end of file diff --git a/src/GS009/404.html b/src/GS009/404.html new file mode 100644 index 00000000..2cc9f4b4 --- /dev/null +++ b/src/GS009/404.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +Page not found | yaml_title_replace + + + + + + + + + + + + + + + + +
+ + + +
+ +
+
+ +
+
+
+
+
+

Page not found

+

The page you requested cannot be found (perhaps it was moved or renamed).

+

You may want to try searching to find the page's new location, or use +the table of contents to find the page you are looking for.

+
+

+

+
+
+ +
+ + +
+ +
+ + + + + + + diff --git a/src/GS009/css/bootstrap.min.css b/src/GS009/css/bootstrap.min.css new file mode 100644 index 00000000..8ceefe5e --- /dev/null +++ b/src/GS009/css/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;/* flex:0 0 100%; */max-width:100%;}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 0%;flex:1 1 0%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal .list-group-item.active{margin-top:0}.list-group-horizontal .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm .list-group-item.active{margin-top:0}.list-group-horizontal-sm .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md .list-group-item.active{margin-top:0}.list-group-horizontal-md .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg .list-group-item.active{margin-top:0}.list-group-horizontal-lg .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl .list-group-item.active{margin-top:0}.list-group-horizontal-xl .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush .list-group-item{border-right-width:0;border-left-width:0;border-radius:0}.list-group-flush .list-group-item:first-child{border-top-width:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;overflow-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/src/GS009/css/hamburgers.css b/src/GS009/css/hamburgers.css new file mode 100644 index 00000000..8e49de35 --- /dev/null +++ b/src/GS009/css/hamburgers.css @@ -0,0 +1,93 @@ +/*! + * Hamburgers + * @description Tasty CSS-animated hamburgers + * @author Jonathan Suh @jonsuh + * @site https://jonsuh.com/hamburgers + * @link https://github.com/jonsuh/hamburgers + */ +.hamburger { + padding: 15px 15px; + display: inline-block; + cursor: pointer; + transition-property: opacity, filter; + transition-duration: 0.15s; + transition-timing-function: linear; + font: inherit; + color: inherit; + text-transform: none; + background-color: transparent; + border: 0; + margin: 0; + overflow: visible; } + .hamburger:hover { + opacity: 0.7; } + .hamburger.is-active:hover { + opacity: 0.7; } + .hamburger.is-active .hamburger-inner, + .hamburger.is-active .hamburger-inner::before, + .hamburger.is-active .hamburger-inner::after { + background-color: #fbfbfb; } + +.hamburger-box { + width: 40px; + height: 24px; + display: inline-block; + position: relative; } + +.hamburger-inner { + display: block; + top: 50%; + margin-top: -2px; } + .hamburger-inner, .hamburger-inner::before, .hamburger-inner::after { + width: 40px; + height: 4px; + background-color: #000; + border-radius: 4px; + position: absolute; + transition-property: transform; + transition-duration: 0.15s; + transition-timing-function: ease; } + .hamburger-inner::before, .hamburger-inner::after { + content: ""; + display: block; } + .hamburger-inner::before { + top: -10px; } + .hamburger-inner::after { + bottom: -10px; } + +/* + * Arrow + */ +.hamburger--arrow.is-active .hamburger-inner::before { + transform: translate3d(-8px, 0, 0) rotate(-45deg) scale(0.7, 1); } + +.hamburger--arrow.is-active .hamburger-inner::after { + transform: translate3d(-8px, 0, 0) rotate(45deg) scale(0.7, 1); } + +/* + * Collapse + */ +.hamburger--collapse .hamburger-inner { + top: auto; + bottom: 0; + transition-duration: 0.13s; + transition-delay: 0.13s; + transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); } + .hamburger--collapse .hamburger-inner::after { + top: -20px; + transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1), opacity 0.1s linear; } + .hamburger--collapse .hamburger-inner::before { + transition: top 0.12s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1), transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19); } + +.hamburger--collapse.is-active .hamburger-inner { + transform: translate3d(0, -10px, 0) rotate(-45deg); + transition-delay: 0.22s; + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); } + .hamburger--collapse.is-active .hamburger-inner::after { + top: 0; + opacity: 0; + transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333), opacity 0.1s 0.22s linear; } + .hamburger--collapse.is-active .hamburger-inner::before { + top: 0; + transform: rotate(-90deg); + transition: top 0.1s 0.16s cubic-bezier(0.33333, 0, 0.66667, 0.33333), transform 0.13s 0.25s cubic-bezier(0.215, 0.61, 0.355, 1); } diff --git a/src/GS009/custom.css b/src/GS009/custom.css new file mode 100644 index 00000000..5062cb1d --- /dev/null +++ b/src/GS009/custom.css @@ -0,0 +1,508 @@ +/* Import fonts */ +@import url("https://fonts.googleapis.com/css2?family=Karla:wght@300;400;700&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;700;800&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@300;400;700&display=swap"); +@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"); + + +/* to-do */ +.todo { + background-color: red; + color:#eeeeee; +} + + +.in-view { + background-color: #ab8b9b; + + padding-left: 3%; + padding-top: 2%; + padding-bottom: 2%; + padding-right: 10%; + + border-radius: 0.5em; +} + +/* Generics */ +body { overflow-x: hidden; } + +p, span, li { + color: #434662; + font-family: 'Karla', sans-serif; + font-size: 1em !important; + text-align: left; + line-height: 1.6em !important; +} + +a { + color: #936287 !important; + text-decoration: underline !important; + background-color: transparent; +} + +a:hover { + color: #caabbe !important; + text-decoration: underline; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Inter', sans-serif !important; + font-weight: bold !important; + color: #434662; + line-height: 140%; + margin-bottom: 0.6em !important; + margin-top: 1em !important; +} + +h1 { font-size: 240% !important; } + +h2 { font-size: 200% !important; } + +h3 { font-size: 160% !important; } + +h4 { font-size: 120% !important; } + +h5 { font-size: 100% !important; } + +/* Sidebar and toc */ + +.sidebar { + background-color: #7a3884; + color: #fbfbfb; + position: fixed; + top: 0; + left: 0; + bottom: 0; + z-index: 100; + width: 20%; + overflow-y: visible; +} + +.sidebar-wrapper { + padding: 5% 10%; + width: 100%; + height: 100%; + overflow: scroll; +} + +.sidebar-wrapper::-webkit-scrollbar { + width: 0 !important; + background: transparent !important; +} + +.sidebar-title-wrapper { + margin: 10% 5% 20% 5%; +} + +.sidebar-title { + text-align: left !important; +} + +.sidebar-title h1 { + color: #fbfbfb !important; +} + +.sidebar-title:after { + content: ""; + background: #fbfbfb; + height: 0.01em; + width: auto; + display: block; + margin-top: 2em; + margin-bottom: 2em; +} + +.sidebar-logo { + display: block; + margin-bottom: 1.8em; +} + +.abstract-sidebar p { + color: #fbfbfb; + font-size: 90%; +} + +.sidebar-nav { + margin: 0; +} + +.sidebar .navbar-toggle { + display: none; +} + +#TOC ul { + position: relative; + padding-inline-start: 6%; +} + +#TOC li { + list-style: none; + padding-bottom: 0.6em; +} + +#TOC > ul > li > a { + height: auto; + font-family: 'Inter', sans-serif; + font-size: 120%; + font-weight: bold; + padding-bottom: 0.6em; + text-decoration: none !important; +} + +#TOC li > a { + color: #fbfbfb !important; + width: 100%; + max-width: 300px; + display: flex; + align-items: flex-start; + flex-direction: row; + justify-content: flex-start; + font-family: 'Inter', sans-serif; + text-decoration: none !important; +} + +#TOC li > a:hover { text-decoration: underline !important; } + +.toc-section-number { + color: inherit; + padding-right: 0.4em; + margin-bottom: 0.2em !important; + display: none; +} + +/* Main content */ + +.main-content { + background-color: #fff; + display: flex; + position: relative; + min-height: 100vh; + height: auto; + width: auto; + justify-content: space-between; + flex-direction: column; + align-items: stretch; +} + +.header-section-number { + display: none; +} + +.main-content-wrapper { padding-bottom: 15%; } + +.level1 { /* wraps around main content */ + flex: 1 0 auto; + justify-content: space-between; + margin-left: 20%; + padding: 2em 3em; + max-width: 60%; + height: auto; +} +.level1 img { + max-width: 100%; + padding: 1em 0; +} + +.level1 .figure { padding: 1em 0; } + +.level1 p, .level1 span { margin-bottom: 1rem !important; } + +/* Title */ + +#title-container { + text-align: left; + margin-left: 20%; + padding: 2em 3em; +} + +#title-container:after { + content: ""; + background: #434662; + display: block; + position: relative; + height: 0.01em; + width: auto; + margin-top: 2em; +} + +/* Tables */ + +table .header { + background-color: #7a3884; + color: #fbfbfb !important; +} + +table .odd { + background-color: #FCFCFC; +} + +table .even { + background-color: #F5F5F5; +} + +table th, +table td { + border-right: 1px solid #ffffff; + padding: 0.8em; + font-family: 'Karla', sans-serif; +} + +/* Buttons */ + +.btn { + font-weight: bold !important; + font-family: 'Inter', sans-serif; + color: #fbfbfb !important; + background-color: #7a3884 !important; + border: none !important; + margin: 0.8em 0.8em !important; + padding: 0.4em 0.8em !important; + border-radius: 3 !important; + display:block +} + +.btn:hover { + color: #fbfbfb !important; + text-decoration: none; + background-color: #ab8b9b !important; +} + +.copy-button { + visibility: hidden; + position: absolute; + top: 0px; + right: 0px; + width: 2.5rem; + height: 2.5rem; + padding: 5px; + background-color: transparent; + border: 1px solid #434662; + border-radius: 3px; + cursor: pointer; + } + +.copy-button{ + color: #8588a2; +} + +.copy-button:hover{ + color: #434662; +} + +.copy-button::before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + content: "\f0c5"; + } + +.copy-button.show-checkmark::before { + content: "\f00c"; + color:#0f9400; +} + +.code-box:hover .copy-button, +.commandline-box:hover .copy-button { + visibility: visible; + } + + +/* Footer */ + +.footer { + display: flex; + position: absolute; + bottom: 0; + width: 100%; + height: auto; + padding-top: 4em; + padding-bottom: 2em; + flex-shrink: 0; + margin: 0; + flex-direction: column; + align-items: flex-end; +} + +.footer:before { + content: ""; + background-image: url(img/Gispo_tausta.png); + background-repeat: no-repeat; + background-size: cover; + display: block; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0.4; + z-index: 1; + clip-path: polygon(0 10%, 20% 15%, 40% 35%, 54% 20%, 66% 40%, 78% 10%, 85% 15%, 90% 0%, 100% 0, 100% 100%, 0 100%); +} + +.footer-container { + display: flex; + align-items: flex-start; + justify-content: space-around; + z-index: 2; +} + +.footer-info { + padding: 0 1.6em; + text-align: right; +} + +.footer-version { position: relative; } + +.license { padding-top: 10%; } + +.footer-contact { + margin: 0 20px; +} +.footer-contact-info { + display: block; + text-align: right; +} + +.footer-copyright-year { font-size: 0.5rem; } + +/* Content boxes */ + +.hint-box { + background: #434662; + padding: 10px; + border: none; + margin-bottom: 1rem; + border-radius: 3px; +} + +.hint-box p { + color: #fbfbfb; + margin: 0 !important; +} + +.note-box { + background: #ffffff; + padding: 10px; + border: none; + margin-bottom: 1rem; + border-radius: 3px; +} + +.note-box p { + color: #434662; + margin: 0 !important; +} + +.code-box { + position: relative; + background: #f5d2cc; + padding-top: 0.1rem; + padding-bottom: 0.1rem; + padding-left: 1rem; + padding-right: 1rem; + border: none; + display: flex; + align-items: center; + margin-bottom: 1rem; + min-height: 2.5rem; + border-radius: 3px; +} + +code span { + font-family: 'Source Code Pro', monospace; +} + +.code-box p { + color: #000000; + font-family: 'Source Code Pro', sans-serif !important; + margin: 0 !important; +} + +.file-content-box { + background: #caabbe; + padding: 10px; + border: none; + margin-bottom: 1rem; + border-radius: 3px; +} + +.file-content-box p { + color: #000000; + margin: 0 !important; +} + +.commandline-box { + position: relative; + background: #cccccc; + padding-top: 0.1rem; + padding-bottom: 0.1rem; + padding-left: 1rem; + padding-right: 1rem; + border: none; + display: flex; + align-items: center; + margin-bottom: 1rem; + min-height: 2.5rem; + border-radius: 3px; +} + +.commandline-box p { + font-family: 'Source Code Pro', monospace; + color: #000000; + margin: 0 !important; +} + +.hidden-box { + display: none; + padding: 1rem; + background: #f0f0f079; +} + +/* Media queries */ +@media (max-width: 1540px) { + .sidebar { width: 320px; } + .main-content-wrapper { padding-bottom: 200px; } + #title-container { margin-left: 320px; } + .level1 { + margin-left: 320px; + width: calc(100% - 320px); + } +} + +@media (max-width: 1199px) and (min-width: 992px) { .level1 { padding: 80px 40px 25px; } } + +/* Hide sidebar */ +@media (max-width: 991px) { + .sidebar { + width: 320px; + left: -320px; + transition: all 0.3s ease; + } + + .sidebar.show { left: 0; } + .sidebar-wrapper { padding: 15px; } + + .sidebar .navbar-toggle { + display: inline-block; + position: fixed; + left: 20px; + padding: 10px 15px; + transition: all 0.3s ease; + border-radius: 0; + outline: none; + } + + + #title-container { margin-left: 0; } + .level1 { + margin-left: 0; + padding: 50px 40px; + width: 100%; + max-width: none; + } + .footer { margin-left: 0; } +} + +@media (max-width: 767px) { + .level1 { padding: 60px 10px; } +} + diff --git a/src/GS009/custom.html b/src/GS009/custom.html new file mode 100644 index 00000000..cf990842 --- /dev/null +++ b/src/GS009/custom.html @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + +$if(url)$$endif$ +$if(cover-image)$$endif$ +$if(description)$$endif$ +$if(github-repo)$$endif$ + +$for(author-meta)$ + +$endfor$ + +$if(date-meta)$ + +$endif$ + +$if(math)$ + +$math$ +$endif$ + + + +$if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ + +$for(header-includes)$ +$header-includes$ +$endfor$ + +$if(highlightjs)$ + + + + +$endif$ + +$if(highlighting-css)$ + + +$endif$ + +$for(css)$ + +$endfor$ + + + + + + + + +$for(include-before)$ +$include-before$ +$endfor$ + +
+ + + +
+ + + +
+ +$if(title)$ +

$title$

+$if(subtitle)$ +

$subtitle$

+$endif$ + +$for(author)$ +$if(author.name)$ +

$author.name$

+ +$if(author.affiliation)$ +
$author.affiliation$
+$endif$ + +$if(author.email)$ +$author.email$
+$endif$ +$else$ +

$author$

+$endif$ +$endfor$ + +$if(date)$ +

Version: $date$

+$endif$ + +$if(abstract)$ +

$abstract$

+$endif$ + +$endif$ +
+ + + + + + + +$body$ + + +
+ + +
+ +
+ +$for(include-after)$ +$include-after$ +$endfor$ + + + + + + diff --git a/src/GS009/img/Gispo_tausta.png b/src/GS009/img/Gispo_tausta.png new file mode 100644 index 00000000..9a59898d Binary files /dev/null and b/src/GS009/img/Gispo_tausta.png differ diff --git a/src/GS009/img/JHSsuositus.png b/src/GS009/img/JHSsuositus.png new file mode 100644 index 00000000..81a2e475 Binary files /dev/null and b/src/GS009/img/JHSsuositus.png differ diff --git a/src/GS009/img/batchrun.png b/src/GS009/img/batchrun.png new file mode 100644 index 00000000..f8731e5f Binary files /dev/null and b/src/GS009/img/batchrun.png differ diff --git a/src/GS009/img/by-nd.svg b/src/GS009/img/by-nd.svg new file mode 100644 index 00000000..6efd00d8 --- /dev/null +++ b/src/GS009/img/by-nd.svg @@ -0,0 +1,203 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/GS009/img/createdb.png b/src/GS009/img/createdb.png new file mode 100644 index 00000000..61f1a475 Binary files /dev/null and b/src/GS009/img/createdb.png differ diff --git a/src/GS009/img/gispo_white.png b/src/GS009/img/gispo_white.png new file mode 100644 index 00000000..6bd5633c Binary files /dev/null and b/src/GS009/img/gispo_white.png differ diff --git a/src/GS009/img/gispo_white_sm.png b/src/GS009/img/gispo_white_sm.png new file mode 100644 index 00000000..678ab928 Binary files /dev/null and b/src/GS009/img/gispo_white_sm.png differ diff --git a/src/GS009/img/gispologosvg.svg b/src/GS009/img/gispologosvg.svg new file mode 100644 index 00000000..1a0bfada --- /dev/null +++ b/src/GS009/img/gispologosvg.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/GS009/img/open_terminal.gif b/src/GS009/img/open_terminal.gif new file mode 100644 index 00000000..9ee6e0c2 Binary files /dev/null and b/src/GS009/img/open_terminal.gif differ diff --git a/src/GS009/img/paikkatietoikkuna.png b/src/GS009/img/paikkatietoikkuna.png new file mode 100644 index 00000000..630a9e3f Binary files /dev/null and b/src/GS009/img/paikkatietoikkuna.png differ diff --git a/src/GS009/img/pgadmin_create_server.gif b/src/GS009/img/pgadmin_create_server.gif new file mode 100644 index 00000000..fc5deaea Binary files /dev/null and b/src/GS009/img/pgadmin_create_server.gif differ diff --git a/src/GS009/img/pgadmin_geom.png b/src/GS009/img/pgadmin_geom.png new file mode 100644 index 00000000..50aed6b6 Binary files /dev/null and b/src/GS009/img/pgadmin_geom.png differ diff --git a/src/GS009/img/pgadmin_query_tool.gif b/src/GS009/img/pgadmin_query_tool.gif new file mode 100644 index 00000000..3600d973 Binary files /dev/null and b/src/GS009/img/pgadmin_query_tool.gif differ diff --git a/src/GS009/img/pgadmin_splash.png b/src/GS009/img/pgadmin_splash.png new file mode 100644 index 00000000..09a2d18b Binary files /dev/null and b/src/GS009/img/pgadmin_splash.png differ diff --git a/src/GS009/img/pgadminback.png b/src/GS009/img/pgadminback.png new file mode 100644 index 00000000..f3104dd2 Binary files /dev/null and b/src/GS009/img/pgadminback.png differ diff --git a/src/GS009/img/pgadminback2.png b/src/GS009/img/pgadminback2.png new file mode 100644 index 00000000..1b1cd680 Binary files /dev/null and b/src/GS009/img/pgadminback2.png differ diff --git a/src/GS009/img/pgadmindb2.png b/src/GS009/img/pgadmindb2.png new file mode 100644 index 00000000..65083b05 Binary files /dev/null and b/src/GS009/img/pgadmindb2.png differ diff --git a/src/GS009/img/pgadmindbluo.png b/src/GS009/img/pgadmindbluo.png new file mode 100644 index 00000000..b32b1e6d Binary files /dev/null and b/src/GS009/img/pgadmindbluo.png differ diff --git a/src/GS009/img/pgadmindbluo2.png b/src/GS009/img/pgadmindbluo2.png new file mode 100644 index 00000000..0d87dc5d Binary files /dev/null and b/src/GS009/img/pgadmindbluo2.png differ diff --git a/src/GS009/img/pgadmindisplay.png b/src/GS009/img/pgadmindisplay.png new file mode 100644 index 00000000..63bbe220 Binary files /dev/null and b/src/GS009/img/pgadmindisplay.png differ diff --git a/src/GS009/img/pgadminrestore.png b/src/GS009/img/pgadminrestore.png new file mode 100644 index 00000000..cec2b434 Binary files /dev/null and b/src/GS009/img/pgadminrestore.png differ diff --git a/src/GS009/img/pgadminrooli.png b/src/GS009/img/pgadminrooli.png new file mode 100644 index 00000000..9acdcea4 Binary files /dev/null and b/src/GS009/img/pgadminrooli.png differ diff --git a/src/GS009/img/pgadminylapalkki.png b/src/GS009/img/pgadminylapalkki.png new file mode 100644 index 00000000..c7274d98 Binary files /dev/null and b/src/GS009/img/pgadminylapalkki.png differ diff --git a/src/GS009/img/pgadylapalkki.png b/src/GS009/img/pgadylapalkki.png new file mode 100644 index 00000000..c5aab82e Binary files /dev/null and b/src/GS009/img/pgadylapalkki.png differ diff --git a/src/GS009/img/psql_start.png b/src/GS009/img/psql_start.png new file mode 100644 index 00000000..63693bf4 Binary files /dev/null and b/src/GS009/img/psql_start.png differ diff --git a/src/GS009/img/qgisDbmanager.png b/src/GS009/img/qgisDbmanager.png new file mode 100644 index 00000000..7bdd6a93 Binary files /dev/null and b/src/GS009/img/qgisDbmanager.png differ diff --git a/src/GS009/img/qgis_add_data.png b/src/GS009/img/qgis_add_data.png new file mode 100644 index 00000000..1a194efe Binary files /dev/null and b/src/GS009/img/qgis_add_data.png differ diff --git a/src/GS009/img/qgis_batch_load.png b/src/GS009/img/qgis_batch_load.png new file mode 100644 index 00000000..ded9683a Binary files /dev/null and b/src/GS009/img/qgis_batch_load.png differ diff --git a/src/GS009/img/qgis_pg_connection.png b/src/GS009/img/qgis_pg_connection.png new file mode 100644 index 00000000..fd65e533 Binary files /dev/null and b/src/GS009/img/qgis_pg_connection.png differ diff --git a/src/GS009/img/qgistasot.png b/src/GS009/img/qgistasot.png new file mode 100644 index 00000000..096c25d5 Binary files /dev/null and b/src/GS009/img/qgistasot.png differ diff --git a/src/GS009/img/run_cell.gif b/src/GS009/img/run_cell.gif new file mode 100644 index 00000000..3d7788f8 Binary files /dev/null and b/src/GS009/img/run_cell.gif differ diff --git a/src/GS009/img/yhteyspg.png b/src/GS009/img/yhteyspg.png new file mode 100644 index 00000000..275767cd Binary files /dev/null and b/src/GS009/img/yhteyspg.png differ diff --git a/src/GS009/index.Rmd b/src/GS009/index.Rmd new file mode 100644 index 00000000..e240f64c --- /dev/null +++ b/src/GS009/index.Rmd @@ -0,0 +1,34 @@ +--- +title: "PostgreSQL ja PostGISin perusteet" +author: "Gispo Oy" +date: "`r Sys.Date()`" +site: "bookdown::bookdown_site" +abstract: "Kurssi PostGISin yleisimpiin käyttötapauksiin." +output: + bookdown::html_book: + toc: true + toc_depth: 2 + number_sections: true + pandoc_args: ["--number-sections"] + theme: null + template: custom.html + css: custom.css + split_by: rmd + +documentclass: book +--- + +# 1. Johdanto + +Tervetuloa kurssin harjoitusten pariin! + +Näiden harjoitusten avulla voit tutustua itsenäisesti PostgreSQL-tietokantajärjestelmän PostGIS-lisäosaan. Valitse vasemmalta haluamasi aihe. + +## 1.1 Harjoitusmateriaalin lisenssi + +- Harjoitusmateriaalit on julkaistu avoimella lisenssillä. Käytettävä lisenssi on [Creative Commons Nimeä-EiMuutoksia 4.0](https://creativecommons.org/licenses/by-nd/4.0/deed.fi). + +Harjoituksissa käytettävät aineistot: + +- 1_milj_Shape_etrs_shape.zip - ladattu 5.7.2023 Maanmittauslaitoksen Karttapaikasta (Maastokartta 1:1 000 000). Jaettu lisenssillä [Creative Commons Nimeä 4.0](https://creativecommons.org/licenses/by/4.0/deed.fi) +- airports.dat - ladattu [Openflights](https://openflights.org/data.html)- sivustolta. Lentokenttäaineisto on julkista (public domain). diff --git a/src/GS009/index.html b/src/GS009/index.html new file mode 100644 index 00000000..2d254291 --- /dev/null +++ b/src/GS009/index.html @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +yaml_title_replace + + + + + + + + + + + + + + + + +
+ + + +
+ +
+
+ +
+
+
+
+ +
+ +

yaml_title_replace

+ +

Gispo author_replace

+ +

Version: 2024-09-24

+ +

abstract_replace

+ +
+ +
+

document_title_replace

+
+

Kurssimateriaalien lataaminen

+

Voit ladata harjoituksissa käytettävän kurssihakemiston tästä linkistä:

+ +
+
+

Lukuohje

+

Web-selaimessa suoritettavat komennot on merkitty seuraavasti:

+ +

Komentorivillä suoritettavat komennot on merkitty seuraavasti:

+
+
sudo lsb_release -a
+
+

Tiedostojen sisältö on esitetty seuraavasti:

+
+

#IPv4 local connections: #host all all 127.0.0.1/32 md5

+
+

HTML- ja CSS-koodit, SQL-komennot sekä Python-scriptit on esitetty seuraavasti:

+
+
SELECT version();
+
+

Kysymykset, lisätiedot ja vihjeet on esitetty seuraavasti:

+
+

Mistä löydät tietoa GeoServeristä?

+

GeoServerillä on omat kotisivut.

+

Psst! Tietoa GeoServeristä löydät internetistä.

+
+
+
+

Mistä lisätietoja?

+

Ohessa muutamia web-sivustoja, joista saat lisätietoja:

+ + + + +
+
+

Virheet

+

Jos havaitset materiaalissa virheitä, niin pyydämme ilmoittamaan niistä kouluttajalle tai sähköpostilla .

+
+
+

Lisenssi ja oikeudet

+

Nämä materiaalit on “license_title_replace”- kurssille kehittänyt Gispo Suomi Oy. Materiaalit on lisensoitu seuraavalla lisenssillä: CC BY-ND 4.0

+
+
+

+

+
+
+ +
+ + +
+ +
+ + + + + + + diff --git a/src/GS009/js/answer-key.js b/src/GS009/js/answer-key.js new file mode 100644 index 00000000..cf1c7ecd --- /dev/null +++ b/src/GS009/js/answer-key.js @@ -0,0 +1,110 @@ +var hiddenBoxes = document.getElementsByClassName("hidden-box"); + +const filePath = window.location.pathname; + +const directoryName = filePath.substring(0, filePath.lastIndexOf('/')); + +let language; +if (directoryName.includes("_eng")) { + language = "EN"; +} else if (directoryName.includes("_sv")) { + language = "SV"; +} else { + language = "FI"; +} + +for (var i = 0; i < hiddenBoxes.length; i++) { + hiddenBoxes[i].id = "hidden-box-" + (i + 1); +} + +const codeBoxes = document.querySelectorAll('.code-box, .commandline-box'); + +codeBoxes.forEach(box => { + const copyButton = document.createElement('button'); + copyButton.className = 'copy-button'; + + copyButton.addEventListener('click', () => { + const text = box.innerText.trim(); + + navigator.clipboard.writeText(text) + .then(() => { + copyButton.classList.add('show-checkmark'); + setTimeout(() => { + copyButton.classList.remove('show-checkmark'); + }, 1000); + }) + .catch(err => { + console.error('Failed to copy text:', err); + }); + }); + + box.appendChild(copyButton); +}); + +let show; +let hide; +let next; +let previous; + +switch (language) { + case "EN": + show = "Show "; + hide = "Hide "; + next = "Next"; + previous = "Previous"; + break; + case "SV": + show = "Visa "; + hide = "Dölj "; + next = "Nästa"; + previous = "Tillbaka"; + break; + default: + show = "Näytä "; + hide = "Piilota "; + next = "Seuraava"; + previous = "Edellinen"; +} + +const navButtons = [...document.getElementsByClassName('btn-default')]; +navButtons.forEach(button => { + if (button.textContent === "Next") + { + button.textContent = next; + } + else if (button.textContent === "Previous") + { + button.textContent = previous; + } +}); + +const answerButtons = [...document.getElementsByClassName('answer_btn')]; +answerButtons.forEach(button => { + button.textContent = show + button.textContent; +}); + +function toggleAnswer(button) { + let buttons = document.getElementsByClassName('answer_btn'); + let buttonIndex = Array.from(buttons).indexOf(button) + 1; + + let buttonTextInput = button.textContent; + let words = buttonTextInput.split(" "); + let originalButtonText = words.slice(1).join(' '); + + let boxId = "hidden-box-" + buttonIndex; + let hiddenBox = document.getElementById(boxId); + + if (hiddenBox) { + let currentDisplay = window.getComputedStyle(hiddenBox).getPropertyValue("display"); + if (currentDisplay === "none") { + hiddenBox.style.display = "block"; + button.textContent = hide + originalButtonText; + } else { + hiddenBox.style.display = "none"; + button.textContent = show + originalButtonText; + } + } + else { + button.textContent = "ERROR: Could not find hidden-box"; + } +} diff --git a/src/GS009/js/nav-script.js b/src/GS009/js/nav-script.js new file mode 100644 index 00000000..c4aff29b --- /dev/null +++ b/src/GS009/js/nav-script.js @@ -0,0 +1,74 @@ +function navToggle() { + let sidebar = document.getElementById('sidebar'); + sidebar.classList.toggle('show'); + let hamburger = document.querySelector('.hamburger') + hamburger.classList.toggle('is-active'); +} + +const sidebarLinks = document.querySelectorAll('.sidebar-nav a'); +const documentFileName = window.location.pathname.split('/').pop(); + +var matchingLinks = []; + +sidebarLinks.forEach(function(link) { + var linkHref = link.getAttribute('href').split('#')[0]; + var linkFileName = linkHref.split('/').pop(); + if (linkFileName === documentFileName) + matchingLinks.push(link); + +}); + + +const headers = document.querySelectorAll( + "h1:not(.sidebar-nav h1), " + + "h2, " + + "h3" +); + + +// Jump to to current document's title in the sidebar + +document.addEventListener('DOMContentLoaded', function() { + var pageTitle = document.title; + + var targetLink = null; + + matchingLinks.forEach(function(link) { + if (pageTitle.includes(link.textContent.trim())) + { + targetLink = link; + return; + } + }); + + if (targetLink) { + targetLink.classList.add('in-view'); + targetLink.scrollIntoView({ + behavior: 'instant', + block: 'center' + }); + } +}); + +// Highlight the header in the sidebar you're currently scrolling at in the main body + +window.addEventListener("scroll", () => { + headers.forEach((header) => { + const headerTop = header.offsetTop; + const headerHeight = header.clientHeight; + + if (scrollY >= (headerTop - 50) - headerHeight) + { + current = header; + } + + matchingLinks.forEach((link) => { + link.classList.remove("in-view"); + if (link.textContent == current.textContent) + { + link.classList.add('in-view'); + } + }); + }); +}); + diff --git a/src/GS009_eng/01_exercise_1.Rmd b/src/GS009_eng/01_exercise_1.Rmd new file mode 100644 index 00000000..53965f64 --- /dev/null +++ b/src/GS009_eng/01_exercise_1.Rmd @@ -0,0 +1,236 @@ +# Exercise 1: Training environment + +**Contents** -- This exercise is an introduction to the pgAdmin 4 interface and psql. The exercise also covers how to create a new PostGIS database. + +**Goal** -- After the exercise the trainee understands the basics of using pgAdmin 4 and psql. + +## Exercise 1.1: pgAdmin 4 + +Start up pgAdmin 4 by following this link: [/pgadmin](/pgadmin). You can log into pgAdmin 4 which is hosted on a remote server with the following credentials: + +TODO: päivitä ohjeet kirjautumiseen + +![pgAdmin- logging in](img/pgadmin_splash.png) + +### Registering a server connection + +Connect the training environment's database to pgAdmin by right clicking **Servers** and choosing **Register \> Server...**. Enter the following information: + +TODO: päivitä ohjeet kirjautumiseen + +- In the General tab + - Name: Name of the connection (typically \@\) + - In the Connection tab + - Host: **dbhost** + - Port: **5432** + - Maintenance database: **postgres** +- Choose **Save password** if you don't want to rewrite your password when opening the connection + +You can inspect the connected database in pgAdmin from the different tabs in the top panel: + +![](img/pgadylapalkki.png) + +PostGIS databases can also be used in other applications (with the psql commandline tool or with the QGIS **DB Manager**). The database looks like this in the QGIS **database manager**: + +![](img/qgisDbmanager.png) + +### Creating the training database + +Let's create a database named **trainingdatabase** to be used throughout the exercises. This can be done through the pgAdmin **Graphical User Interface (GUI)**: + +![](img/pgadmindbluo.png) + +::: hint-box +**Note!** The database can also be created and deleted with the following SQL commands: + +**CREATE DATABASE** trainingdatabase;\ +**DROP DATABASE** trainingdatabase; +::: + +### Executing SQL queries + +The majority of the exercises involve using SQL. You can execute the SQL queries and commands using pgAdmin's **Query Tool**, which can be opened with the following instructions: + +- Choose your database cluster from the **Servers** section +- Choose the database which was just created (**trainingdatabase**) +- From the top panel click **Tools \> Query Tool** + +You can write the SQL command in the window which opens up and then execute it by pressing the "play" button (**Execute/Refresh**) or by pressing **F5**. If you want to execute only a part of the query, you can select the part using your mouse and then press **F5**. The results of the query appear in the bottom panel. You may also save your SQL commands as **.sql** files from which they can be loaded later on. + +![](img/pgadmin_query_tool.gif) + +Let's add the PostGIS extension to **trainingdatabase** using the following command: + +::: code-box +``` sql +CREATE EXTENSION IF NOT EXISTS postgis; +``` +::: + +::: hint-box +What is included in the spatial_ref_sys table? + +What views were created in the database? What information do they contain? +::: + +A new table can be created by executing the following SQL command in the **Query Tool** + +::: code-box +``` sql +-- Introduction to PostGIS +CREATE TABLE test_tmp( + id serial, + time time, + num integer); +``` +::: + +::: hint-box +Note that the lines which start with two dashes "\-\-" are comments and do not affect the execution of the SQL command. +::: + +Tables can also be created based on SQL query results. + +Let's add rows to the table that was just created: + +::: code-box +``` sql +INSERT INTO test_tmp (time,num) +(SELECT now(), generate_series(1,5000)); +``` +::: + +Rows, like tables, can be added based on SQL query results. + +You can list (some of the) the rows you just created with the following query: + +::: code-box +``` sql +SELECT * +FROM test_tmp +LIMIT 10; +``` +::: + +You can delete the table with the following command: + +::: code-box +``` sql +DROP TABLE test_tmp; +``` +::: + +### pg_dump ja pg_restore + +There are separate command-line tools for creating and restoring backups: [pg_dump](https://www.postgresql.org/docs/13/app-pgdump.html) and [pg_restore](https://www.postgresql.org/docs/13/app-pgrestore.html). pgAdmin uses these internally. + +## Exercise 1.2: psql + +In addition to pgAdmin (and QGIS Database Manager) you can also execute SQL command with the psql command-line tool. Open the [command-line](/wetty) to start using psql. First log into the WeTTY terminal emulator: + +TODO: päivitä ohjeet kirjautumiseen + +Connect to your database cluster with the following command: + +::: commandline-box +``` sh +psql -U postgres -h dbhost +``` +::: + +![](img/psql_start.png) + +### Using psql + +Once psql has been opened you can write both psql and SQL commands on the command-line. Commands used during a psql session are called interactive: + +A few examples of interactive psql commands: + +::: commandline-box +``` psql +\d = show tables, views and sequences +\dg = show database cluster roles (users) +\c database_name = connect to database +``` +::: + +Using the `help` or especially `\?` commands you get information about the different commands psql has. You can exit the list by pressing `q`. + +psql commands run on the command-line (not in a psql session) are called non-interactive. These are used especially when you want to run psql straight from the operating system's command-line and the psql commands and SQL scripts are saved in a file. Non-interactive psql is especially well-suited for automating tasks. The commands mentioned previously are good examples of non-interactive psql commands. Try running the following command on the command-line: + +::: commandline-box +``` sh +psql -U postgres -h dbhost -c "select current_database();" +``` +::: + +### Creating a database + +Createdb is a command-line tool which makes creating a database easy. At its easiest you can create a database with the following command: + +::: commandline-box +``` sh +createdb -U postgres -h dbhost new_database +``` +::: + +![](img/createdb.png) + +### Dropping a database + +Like createdb, dropdb is a command-line tool. You can drop (or delete) a database with the following command: + +::: commandline-box +``` sh +dropdb -U postgres -h dbhost database_to_be_deleted +``` +::: + +### Closing the database connection + +To close the connection to a database enter the following command in psql: + +::: commandline-box +`\q` +::: + +### Information about the PostgreSQL installation + +You can query the PostgreSQL version: + +::: code-box +``` sql +SELECT version(); +``` +::: + +You can check which extensions have been created: + +::: code-box +``` sql +SELECT * +FROM pg_extension; +``` +::: + +### Closing the database connection + +Right click the connection you've created and click **Disconnect from server**. + +### Other notes + +If you want to be able to use the PostGIS database from another computer, you have to edit the PostgreSQL configuration file (pg_hba.conf): + +::: code-box +``` mysql +# IPv4 local connections: +#host all all 127.0.0.1/32 md5 +host all all 0.0.0.0/0 trust +``` +::: + +::: hint-box +**NOTE!** This change allows connections from any computer and is a security risk in developmental database systems. +::: + +By default the connection to the database is unprotected. It is recommended to secure the database connection using TLS. diff --git a/src/GS009_eng/02_exercise_2.Rmd b/src/GS009_eng/02_exercise_2.Rmd new file mode 100644 index 00000000..1192b713 --- /dev/null +++ b/src/GS009_eng/02_exercise_2.Rmd @@ -0,0 +1,244 @@ +# Exercise 2: Importing data + +**Contents** -- In this exercise we import spatial data into the PostGIS database. + +**Goal** -- After the exercise the trainee understands the basics of importing spatial data into a database. + +### Preparation + +QGIS has to be installed for importing spatia data. Open [pgAdmin](/pgadmin) in the browser and log in. Open the **Query Tool** (Right click _trainingdatabase_ **->** **Query Tool**). + +## Exercise 2.1: Importing from a text file + +Many point data sets are saved in CSV files, where they are not necessarily in a spatial data format. In the first exercise we'll import a global dataset which contains information about airports. First create a table in the _trainingdatabase_ with the following SQL command: + +::: code-box +``` sql +DROP TABLE IF EXISTS airports; + +CREATE TABLE airports +( + id integer, + name text, + city text, + country text, + IATA_code char(3), + ICAO_code char(4), + latitude numeric, + longitude numeric, + altitude numeric, + timezone text, + dst text, + tz_zone text, + type text, + source text +); +``` +::: + +The data set has been already downloaded from [OpenFlights.org](http://openflights.org/data.html) and added to a folder inside of the database server. + +Inspect the data set. You can open the file in your browser with [this link](/data/airports.dat). + +You can import the data from the CSV file to the table you previously created with this command: + +::: code-box +``` sql +COPY airports +FROM '/home/student/data/airports.dat' +WITH CSV; +``` +::: + +The **COPY** command refers to a file on the disk and imports it. In addition to CSV files the **COPY** command can also refer to [binary formats or text files.](https://www.postgresql.org/docs/current/sql-copy.html) + +Check that the data was correctly imported: + +::: code-box +``` sql +SELECT * +FROM airports +LIMIT 10; +``` +::: + +By inspecting the data set you can see that the table has coordinates, but they've been saved as numerical values and not as geometries / in a geographical data type. + +To be able to use PostGIS functionalities with this data set, you have to add a geometry column to the table. PostGIS has a [function](https://postgis.net/docs/AddGeometryColumn.html) for this purpose. Read the documentation on how this function is used. + +::: code-box +``` sql +SELECT AddGeometryColumn ('airports','geom',4326,'POINT',2); +``` +::: + +Inspect the table again. + +::: code-box +``` sql +SELECT * +FROM airports +LIMIT 10; +``` +::: + +The table now has a new column which is empty. Let's update the contents of the table with the **UPDATE** command. + +In the following command two functions are nested: + +- [ST_MakePoint](https://postgis.net/docs/ST_MakePoint.html) creates a point geometry from text fields. +- [ST_SetSRID](https://postgis.net/docs/ST_SetSRID.html) sets a coordinate reference system for the field based on an EPSG code. + +::: code-box +``` sql +UPDATE airports +SET geom = ST_SetSRID(ST_MakePoint(longitude, latitude),4326); +``` +::: + +Inspect the dataset with the pgAdmin map feature: + +![](img/pgadmin_geom.png) + +## Exercise 2.2: Importing spatial data + +The Natural Earth data used in the coming exercises are uploaded to the [data folder](/data). You can download the postgis_data_package.gpkg from there. + +### Option 1: Importing with QGIS + +QGIS offers a handy graphical user interface for importing spatial data into a PostGIS database. Many QGIS tools also enable flexible loading and editing of data in the database. + +First, let's connect from your local QGIS installation to the PostGIS database used in the training. Open QGIS and create a new database connection by clicking Layer \> Data Source Manager. Choose the PostgreSQL tab and click the 'New' button: + +Enter the following information in the New Connection window: + +![](img/qgis_pg_connection.png) + +Note that the 'Name' field means the name of your connection saved to QGIS and not the name of the database. It is generally a good idea to choose all the options listed under the database connection parameters. For example using estimated table metadata speeds queries up considerably. + +Click **Test Connection** to make sure you can connect to the database and then click **OK**. You can also execute SQL queries inside QGIS using **DB Manager**. + +In addition to the database named "postgres", +connect to the "trainingdatabase" database with QGIS. +We will be operating in this database for the rest of the course. +Creating the connection is nearly identical to +how we connected to the "postgres" database: +you must just specify a different name for the connection +(for example gispo_trainingdatabase). + +Let's create a new schema in the trainingdatabase where we will import the Natural Earth data. Name the new schema 'ne'. Schemas help you organize tables and other relations. You can create the new schema in pgAdmin, QGIS or with the following SQL commands: + +::: code-box +``` sql +CREATE SCHEMA IF NOT EXISTS ne; +``` +::: + +If you cannot see the schema you just created in QGIS, run the following SQL commands and restart the QGIS project. + +::: code-box +``` sql +DROP TABLE IF EXISTS ne.example; + +CREATE TABLE ne.example +( + id integer, + name text +); +``` +::: + +::: code-box +``` sql +INSERT INTO ne.example +VALUES (1, 'test'); +``` +::: + +If you didn't already, download the [Natural Earth data geopackage](/data/postgis_data_package.gpkg) on your computer. You can add the layers to QGIS by clicking Layers \> Add Layer \> Add Vector Layer; opening the Vector tab inside the Data Source Manager, or by dragging and dropping the file from your computer's file manager. + +Import the following layers into QGIS and PostGIS: + +- airports_eu +- capitals_eu +- countries_eu +- countries_world +- railroads_eu +- rivers_eu + +::: hint-box +QGIS might ask about a coordinate transformation. Click **OK** in the window which might open up when trying to add layers. +::: + +Make sure that the QGIS project's Spatial Reference System is set as ETRS89 ETRS89-extended / LAEA Europe (EPSG:3035). You can check the project's SRS in the bottom right corner and the individual layer's SRS by right clicking the layer, selecting **Properties > Source > Assigned Coordinate Reference System**. All layers should be set to EPSG:3035, except the **countries_world** layer, which should be EPSG:4326. + +![](img/qgislayers.png) + +In QGIS, open a processing tool named 'Export to PostgreSQL'. Click on the bottom **Run as Batch Process...** which allows exporting several tables into the database at the same time. Change the parameters so that the layers are exported to the correct schema and database. Using the **Fill Down** button you don't have to individually fill every parameter for each layer. Name the geometry column as "wkb_geometry". Make sure that the geopackage's name is not left in the **Table to export to** field and all the table names are set to export as follows: + +- airports_eu +- capitals_eu +- countries_eu +- countries_world +- railroads_eu +- rivers_eu + +You can check what other parameters the tool has, but leave them unchanged. The final parameters should look like this: + +![](img/batchrun.png) + +Click **Run**! + +Make sure after running the tool that the data sets have been exported correctly. Check possible error messages and change parameters if needed. + +::: code-box +``` sql +SELECT * +FROM ne.countries_world +LIMIT 10; +``` +::: + +### Option 2: Importing with the command line + +Let's create a new schema in the trainingdatabase where we will import the Natural Earth data. Name the new schema 'ne'. Schemas help you organize tables and other relations. You can create the new schema in pgAdmin, QGIS or with the following SQL commands: + +::: code-box +``` sql +CREATE SCHEMA IF NOT EXISTS ne; +``` +::: + +You can import data to a PostGIS database using the **shp2pgsql** or **ogr2ogr2** tools. By running the program without parameters you receive instructions on how to use them. After this you can import data into the schema you just created using the **ogr2ogr** tool. If you've installed the OSGeo4W package (included with QGIS) open the **OSGeo4W Shell** from your start menu and enter the following command: + +::: commandline-box +``` sh +ogr2ogr -f "PostgreSQL" PG:"host= port= dbname= user= password=" \postgis_data_package.gpkg -lco SCHEMA=ne +``` +::: + +Remember to check the file path and the other parameters! + +The parameters used by **ogr2ogr** are as follows: + +::: commandline-box +``` +-f output file format name +-lco layer creation option + +``` +::: + +You can explore the other parameters by +running the **ogr2ogr** command without parameters. + +The **shp2pgsql** tool is included with the PostGIS installation. +With this tool you can create .sql files from .shp files. + +Commandline tools enable you to import several files at once. For example in Windows you can import an entire folder of gml files to a database with the following command: + +::: commandline-box +``` sh +for %i in (*.gml) do ogr2ogr -update -append -f PostgreSQL PG:"host= port=5432 dbname= user= password= schemas=gml" %i +``` +::: diff --git a/src/GS009_eng/03_exercise_3.Rmd b/src/GS009_eng/03_exercise_3.Rmd new file mode 100644 index 00000000..e1e7f873 --- /dev/null +++ b/src/GS009_eng/03_exercise_3.Rmd @@ -0,0 +1,353 @@ +# Exercise 3: Basics of SQL + +**Contents** -- In this exercise we write basic SQL queries. + +**Goal** -- The goal of the exercise is to familiarize oneself with SQL. + +### Preparation + +Open [pgAdmin](/pgadmin) in the browser and log in. Open the **Query Tool** (Right click _trainingdatabase_ **->** **Query Tool**). + + +## Exercise 3.1: Simple SQL queries + +Let's inspect the spatial data sets imported in the last exercise: + +:::code-box +```sql +SELECT +name_en +FROM +ne.countries_world; +``` +::: + +Queries can be filtered with the **WHERE** keyword: + +:::code-box +```sql +SELECT +name_en, wkb_geometry +FROM +ne.countries_world +WHERE +continent = 'Asia'; +``` +::: + +Functions can be used in SQL commands. This way you can for example calculate averages or standard deviations. Next let's inspect the length of different countries' names: + +:::code-box +```sql +SELECT +avg(char_length(name_en)), stddev(char_length(name_en)) +FROM +ne.countries_world +WHERE +continent = 'Europe'; +``` +::: + +With the following SQL statement we see which continents have the longest country names by average: + +:::code-box +```sql +SELECT +continent, avg(char_length(name_en)) +FROM +ne.countries_world +GROUP BY +continent +ORDER BY +avg(char_length(name_en)) DESC; +``` +::: + +## Exercise 3.2 + +Which continent has the longest country names by average? + +::: code-box +```sql +SELECT +... +FROM +... +GROUP BY +... +ORDER BY +... desc +LIMIT ...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Fill in the correct columns, schema and table. Check which functions calculates +-- the average. Use the char_length() function, which returns the length of a +-- string + +SELECT +continent, average_function(char_length(country)) +FROM +schema.table +GROUP BY +continent +ORDER BY +average_function(char_length(country)) desc +LIMIT 1; +``` +::: +::: + + + +::: hidden-box +:::code-box +```sql +SELECT +continent, avg(char_length(name_en)) +FROM +ne.countries_world +GROUP BY +continent +ORDER BY +avg(char_length(name_en)) desc +LIMIT 1; +``` +::: +::: + +## Exercise 3.3 + +Which continent has the shortest country names by average? + +:::code-box +```sql +SELECT +... +FROM +... +GROUP BY +... +ORDER BY +... asc +LIMIT ...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Fill in the correct columns, schema and table. Check which functions calculates +-- the average. Use the char_length() function, which returns the length of a +-- string + +SELECT +continent, average_function(char_length(country)) +FROM +schema.table +GROUP BY +continent +ORDER BY +average_function(char_length(country)) asc +LIMIT 1; +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +continent, avg(char_length(name_en)) +FROM +ne.countries_world +GROUP BY +continent +ORDER BY +avg(char_length(name_en)) asc +LIMIT 1; +``` +::: +::: + +## Exercise 3.4 + +Which country has the longest name in the world? + +:::code-box +```sql +SELECT +... +FROM +... +ORDER BY +... +LIMIT +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Fill in the correct column, schema and table. Choose the function +-- which tells you the length of a string. +SELECT +country, continent, character_length(country) +FROM +schema.table +ORDER BY +character_length(country) desc +LIMIT 1; +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +name_en as "Country", continent as "Continent", char_length(name_en) as "Length" +FROM +ne.countries_world +ORDER BY +char_length(name_en) desc +LIMIT 1; +``` +::: +::: + +## Exercise 3.5 + +How many English country names are 5 letters long? + +:::code-box +```sql +WITH ... AS +( + SELECT ... +) + +SELECT +... +FROM +...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- use a CTE (Common Table Expression) +WITH ltr5 AS +( + + SELECT + ... + FROM + ... + WHERE + ... AND ... +) + +SELECT +count() AS ... -- use the count() function (choose a suitable column from the CTE) + -- You may also define an alias after the AS expression. +FROM +...; -- refer to the CTE +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +WITH ltr5 AS +( + SELECT + name_en as "Country", continent as "Continent", char_length(name_en) as "Length" + FROM + ne.countries_world + WHERE + char_length(name_en) = 5 +) + +SELECT +count("Country") AS "5 letter long country names" +FROM +ltr5; +``` +::: +::: + +## Exercise 3.6 + +Which countries' English and Spanish names are different, but of equal length? +Order the results in a descending order based on the length of the english name. + +:::code-box +```sql +SELECT +... +FROM +... +WHERE +... +ORDER BY +... DESC; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Fill in the columns +SELECT +country_name_en, country_name_es, char_length(country_name_en) AS "Length" +FROM +ne.countries_world +WHERE +country_name_en ... country_name_es AND char_length(country_name_en) ... char_length(country_name_es) +-- fill in the blanks '...' with the correct operators +-- if needed, check the documentation (link below) +ORDER BY +char_length(country_name_en) DESC; +``` +::: +[Operators in the PostgreSQL documentation.](https://www.postgresql.org/docs/9.0/functions-comparison.html) +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +name_en, name_es, char_length(name_en) AS "Length" +FROM +ne.countries_world +WHERE +name_en <> name_es AND char_length(name_en) = char_length(name_es) +ORDER BY +char_length(name_en) DESC; +``` +::: +::: diff --git a/src/GS009_eng/04_exercise_4.Rmd b/src/GS009_eng/04_exercise_4.Rmd new file mode 100644 index 00000000..2b660f86 --- /dev/null +++ b/src/GS009_eng/04_exercise_4.Rmd @@ -0,0 +1,236 @@ +# Exercise 4: Spatial SQL queries + +**Contents** -- In this exercise we explore the basic principles of storing spatial data and try some spatial SQL queries. + +**Goal** -- The goal of the exercise is to understand how PostGIS spatial functions can be used as a part of spatial analyses. + +### Preparation + +Open [pgAdmin](/pgadmin) in the browser and log in. Open the **Query Tool** (Right click *trainingdatabase* **-\>** **Query Tool**). + +### Metadata tables + +All tables containing spatial data are registered in metadata tables: + +| | | +|:------------------------------:|:--------------------------------------:| +| [**geography_columns**]{style="color:purple"} | Columns with a 'Geography' data type | +| [**geometry_columns**]{style="color:purple"} | Columns with a 'Geometry' data type | +| [**raster_columns**]{style="color:purple"} | Columns containg raster data | +| [**raster_overviews**]{style="color:purple"} | Columns containing raster overviews | + +## Exercise 4.1: Metadata of geometries + +Inspect the geometry_columns table. What information do the different columns contain? + +::: code-box +``` sql +SELECT * +FROM +geometry_columns; +``` +::: + +::: hint-box +Is geometry_columns actually a table? +::: + +## Exercise 4.2: Representing geometries + +Let's inspect the format in which spatial data is stored in PostGIS. Execute the following SQL query: + +::: code-box +``` sql +SELECT +name_en, continent, wkb_geometry +FROM +ne.countries_world +WHERE +name_en = 'Ireland'; +``` +::: + +The result tells us that the contents of the column 'wkb_geometry' is in a machine-readable binary format. + +::: hint-box +Hint: it is possible to inspect geometries in a graphical interface in pgAdmin by clicking the map icon ![](img/pgadmin_geom.png) above the geometry column. If the data is in the WGS84 Coordinate Reference System (EPSG: 4326) pgAdmin also adds OpenStreetMap as a basemap. +::: + +You can display the coordinates in a more readable format with the following query: + +::: code-box +``` sql +SELECT +name_en, continent, ST_AsText(wkb_geometry) +FROM +ne.countries_world +WHERE +name_en = 'Ireland'; +``` +::: + +## Exercise 4.3: Functions + +Try out the following functions with Ireland's geometry: + +- ST_Boundary + +::: code-box +``` sql +SELECT +... +FROM +... +WHERE +...; +``` +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +name_en, continent, ST_Boundary() -- fill in the geometry column +FROM +schema.table +WHERE +...; -- select based on the country name +``` +::: +::: + + + +::: hidden-box +::: code-box +```sql +SELECT +name_en, continent, ST_Boundary(wkb_geometry) +FROM +ne.countries_world +WHERE +name_en = 'Ireland'; +``` +::: +::: + +- ST_Centroid + +::: code-box +``` sql +SELECT +... +FROM +... +WHERE +...; +``` +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +name_en, continent, ST_Centroid() -- fill in the geometry column +FROM +schema.table +WHERE +...; -- select based on the country name +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +name_en, continent, ST_Centroid(wkb_geometry) +FROM +ne.countries_world +WHERE +name_en = 'Ireland'; +``` +::: +::: + +- ST_Envelope + +::: code-box +``` sql +SELECT +... +FROM +... +WHERE +...; +``` +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +name_en, continent, ST_Envelope() -- fill in the geometry column +FROM +schema.table +WHERE +...; -- select based on the country name +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +name_en, continent, ST_Envelope(wkb_geometry) +FROM +ne.countries_world +WHERE +name_en = 'Ireland'; +``` +::: +::: + +Note how the geometry type differs based on the function. + +## Exercise 4.4: Spatial indexes + +Inspect the indexes of the ne.countries. + +- Which indexes have been created for the table? + +Indexes can be inspected both with pgAdmin or QGIS's **DB Manager** and also with an SQL query. + +Let's create a spatial index for the railroads_eu table: + +::: code-box +``` sql +CREATE INDEX railroads_eu_wkb_geometry +ON ne.railroads_eu +USING GIST(wkb_geometry); +``` +::: + +You can find indexes in pgAdmin by selecting Schemas \> Tables \> Indexes. + +In psql you can inspect indexes with the following commands: + +::: commandline-box +``` +\dt+ ne.railroads_eu +\di+ ne.railroads_eu +``` +::: + +What is the size of the railroads_eu table and of its index? diff --git a/src/GS009_eng/05_exercise_5.Rmd b/src/GS009_eng/05_exercise_5.Rmd new file mode 100644 index 00000000..93a04825 --- /dev/null +++ b/src/GS009_eng/05_exercise_5.Rmd @@ -0,0 +1,511 @@ +# Exercise 5: Spatial feature geometries + +**Contents** -- In this exercise we explore how PostGIS handles geometries. + +**Goal** -- The goal of the exercise is to understand the basics of processing geometries with PostGIS. + +### Preparation + +Open [pgAdmin](/pgadmin) in the browser and log in. Open the **Query Tool** (Right click *trainingdatabase* **-\>** **Query Tool**). + +## Exercise 5.1 + +First let's create a table to which we can create different geometries: + +::: code-box +``` sql +DROP TABLE IF EXISTS geom_test; + +CREATE TABLE IF NOT EXISTS geom_test +( + gid serial PRIMARY KEY, + name varchar(50), + geom geometry(geometry, 3067) +); +``` +::: + +Add a single point to the table with the following command: + +::: code-box +``` sql +INSERT INTO +geom_test(name, geom) +VALUES +('Single point', 'SRID=3067; POINT(0 0)'); +``` +::: + +You can inspect the table with the following query or with QGIS: + +::: code-box +``` sql +SELECT +name, ST_AsText(geom), ST_GeometryType(geom) +FROM +geom_test; +``` +::: + +## Exercise 5.2 + +Add a linestring and a polygon to the table. + +You may either use the WKT format (LINESTRING(0 1, 2 3) and POLYGON((4 5, 6 7, 8 9, 10 11, 4 5)) or PostGIS functions (ST_MakeLine, ST_MakePolygon, ST_MakeEnvelope). + +Check the documentation for the functions: [8.4 Geometry Constructors](http://postgis.net/docs/reference.html#Geometry_Constructors). + +WKT format: + +::: code-box +``` sql +INSERT INTO + +VALUES +``` +::: + + + +::: hidden-box +::: code-box +``` sql +-- linestring +INSERT INTO +geom_test(name, geom) +VALUES +(..., '...; ...'); -- fill in the blanks '...' + +-- polygon +INSERT INTO +geom_test(name, geom) +VALUES +(..., '...; ...'); -- fill in the blanks '...' +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +INSERT INTO +geom_test(name, geom) +VALUES +('Single linestring', 'SRID=3067; LINESTRING(0 1, 2 3)'); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single polygon', 'SRID=3067; POLYGON((4 5, 6 7, 8 9, 10 11, 4 5))'); +``` +::: +::: + +PostGIS function: + +::: code-box +``` sql +INSERT INTO + +VALUES +``` +::: + + + +::: hidden-box +::: code-box +``` sql +-- check the documentation and fill in the values. +INSERT INTO +geom_test(name,geom) +VALUES +('Simple polygon using ST_MakeEnvelope', ST_MakeEnvelope()); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single point using ST_MakePoint', ST_SetSRID(ST_MakePoint(),3067)); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single linestring using ST_MakeLine', + ST_SetSRID(ST_MakeLine(ST_MakePoint(),ST_MakePoint()),3067)); +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +INSERT INTO +geom_test(name,geom) +VALUES +('Simple polygon using ST_MakeEnvelope', ST_MakeEnvelope(20,20,40,40,3067)); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single point using ST_MakePoint', ST_SetSRID(ST_MakePoint(100,200),3067)); + +INSERT INTO +geom_test(name,geom) +VALUES +('Single linestring using ST_MakeLine', + ST_SetSRID(ST_MakeLine(ST_MakePoint(1,1),ST_MakePoint(50,50)),3067)); +``` +::: +::: + +### Area + +The attributes of geometries can be calculated and used with different SQL functions. With the following command you can find the 10 smallest countries in the EU: + +::: code-box +``` sql +SELECT +name_en as "Name", ST_Area(wkb_geometry) as "Area" +FROM +ne.countries_eu +ORDER BY +ST_Area(wkb_geometry) asc +LIMIT 10; +``` +::: + +The area is in the same units as in the coordinate reference system, in this case square meters. If you want the area f.e. as hectares, you can divide the area by 10 000. + +## Exercise 5.3 + +What is the area of the fifth smallest country in the 'Western Europe' sub-region? Convert the result to square kilometers. + +::: code-box +``` sql +SELECT +... +FROM +... +WHERE +... +ORDER BY +... +LIMIT ... +OFFSET ...; +``` +::: + + + +::: hidden-box +::: code-box +``` sql +-- fill in the columns +-- the round() function rounds the value. The parameter '2' means that the +-- value is returned with two decimal places +SELECT +name_en, subregion +round((ST_Area(geometria)/ ... ::numeric, 2) as "area (Sq. km)" +-- the area will be returned as square meters. Fill in the correct value to +-- convert the result to square kilometers +FROM +ne.countries_eu +WHERE +subregion = 'Western Europe' +ORDER BY +ST_Area(wkb_geometry) ... -- order into ascending order +LIMIT 1 +OFFSET ...; +-- the OFFSET keyword shifts the set of returning rows to start from the +-- row X. Fill in the value which gets you the fifth smallest country. +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +name_en as "Country", subregion As "Sub-region", +round((ST_Area(wkb_geometry)/(1000*1000))::numeric,2) as "area (Sq. km)" +FROM +ne.countries_eu +WHERE +subregion = 'Western Europe' +ORDER BY +ST_Area(wkb_geometry) asc +LIMIT 1 +OFFSET 4; +``` +::: +::: + +### Topology + +You can inspect the topology of geometries in many ways. For example you can find the EU countires which have a 'hole' (interior ring) in them with the following query: + +::: code-box +``` sql +SELECT +name_en as "Country" +FROM +ne.countries_eu +WHERE +ST_NumInteriorRings(ST_GeometryN(wkb_geometry,1)) > 0; +``` +::: + +### Length + +You can calculate the length of linestrings with the **ST_Length** function. For example you can calculate the total length of the railroads_eu data set: + +::: code-box +``` sql +SELECT +sum(ST_Length(wkb_geometry))/1000 as "Railroad length" +FROM +ne.railroads_eu; +``` +::: + +## Exercise 5.4 + +Which 5 EU countries have the most railroads by length? + +::: code-box +``` sql +SELECT +... +FROM +... +GROUP BY +... +ORDER BY +... +LIMIT ...; +``` +::: + + + +::: hidden-box +::: code-box +``` sql +-- Using what function can you calculate the length? +-- Use the SUM function to calculate the total length of a country's railroads +SELECT +country, SUM(length_function(wkb_geometry)/1000) as "Railroad length" +FROM +ne.railroads_eu +GROUP BY +... -- fill in the blank +ORDER BY +SUM(ST_Length(wkb_geometry)/1000) desc +LIMIT 5; +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +country, SUM(ST_Length(wkb_geometry)/1000) as "Railroad length" +FROM +ne.railroads_eu +GROUP BY +country +ORDER BY +SUM(ST_Length(wkb_geometry)/1000) desc +LIMIT 5; +``` +::: +::: + +### Formats + +Previously we converted geometries to a text format. PostGIS also supports other formats: + +::: code-box +``` sql +SELECT +ST_asGeoJSON(wkb_geometry) +FROM +ne.countries_world +WHERE +name_en = 'Sweden'; +``` +::: + +Try out different formats: + +- GML +- SVG +- KML +- X3D +- EWKB, EWKT + +### Data type conversion (casting) + +There are two ways to cast (convert) data types: + +::: code-box +``` mysql +cast(varchar_col AS int) -- SQL compatible +varchar_col::int -- traditional way in PostgreSQL +``` +::: + +::: code-box +``` sql +SELECT CAST('POINT(0 0)' as geometry); +SELECT 'POINT(0 0)'::geometry; +``` +::: + +## Exercise 5.5 + +Create a new spatial data layer from the airport data used in exercise 1. Save the location of the airports in a PostGIS geometry data type. + +Use the following SQL command as an example. It's a good idea to use the LIMIT keyword to inspect only a small portion of the data set: + +::: code-box +``` sql +SELECT name, longitude, latitude, 'POINT(' || longitude || ' '|| latitude || ')' as WKT_new +FROM airports +ORDER BY name +LIMIT 10; +``` +::: + +::: code-box +``` sql +DROP TABLE IF EXISTS airports_geom + +CREATE TABLE airports_geom AS +( + SELECT + ... + FROM + ... +); + +SELECT +... +FROM +... +ORDER BY +... +LIMIT ...; +``` +::: + + + +::: hidden-box +::: code-box +``` sql +-- What function can you use to define a coordinate reference system? +DROP TABLE IF EXISTS airports_geom; + +CREATE TABLE airports_geom AS +( + SELECT + *, aseta_koordinaattijärjestelmä(CAST('...' as geometry),4326) as geometry + FROM + airports +); +-- fill in the CAST() function. + +-- inspect the new table: + +SELECT +name, longitude, latitude, geom +FROM +airports_geom +ORDER BY +name +LIMIT 10; +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql + +DROP TABLE IF EXISTS airports_geom; + +CREATE TABLE airports_geom AS +( + SELECT + *, ST_SetSRID(CAST('POINT(' || longitude || ' '|| latitude || ')' as geometry),4326) as geometry + FROM + airports +); + + +-- inspect the new table: + +SELECT +name, longitude, latitude, geom +FROM +airports_geom +ORDER BY +name +LIMIT 10; +``` +::: +::: + +Should you use 'geometry' or 'geography'? diff --git a/src/GS009_eng/06_exercise_6.Rmd b/src/GS009_eng/06_exercise_6.Rmd new file mode 100644 index 00000000..7d60d73e --- /dev/null +++ b/src/GS009_eng/06_exercise_6.Rmd @@ -0,0 +1,419 @@ +# Exercise 6: Spatial relations + +**Contents** -- In this exercise we try out PostGIS functions for handling spatial relations. + +**Goal** -- The goal of the exercise is to understand PostGIS spatial relation functions and perform simple analyses with them. + +### Preparation + +Open [pgAdmin](/pgadmin) in the browser and log in. Open the **Query Tool** (Right click *trainingdatabase* **-\>** **Query Tool**). + +### Functions + +Most of the following functions are used in the following exercises: + +| PostGIS function | Returns | +|:------------------------------:|:--------------------------------------:| +| ST_Contains(geometry A, geometry B) | TRUE if A contains B | +| ST_Crosses(geometry A, geometry B) | TRUE if A crosses B | +| ST_Disjoint(geometry A , geometry B) | TRUE if geometries do not cross each other | +| ST_Distance(geometry A, geometry B) | Minimum distance between geometries | +| ST_DWithin(geometry A, geometry B, radius) | TRUE if A is closer to B than the given distance | +| ST_Equals(geometry A, geometry B) | TRUE if A is equal to B | +| ST_Intersects(geometry A, geometry B) | TRUE if A intersects B | +| ST_Overlaps(geometry A, geometry B) | TRUE if A and B overlap but are not contained in one another | +| ST_Touches(geometry A, geometry B) | TRUE if the border of A touches B | +| ST_Within(geometry A, geometry B) | TRUE if A is inside B | + +## Exercise 6.1 + +How many airports are within a 50 km radius of the Dublin Airport: + +::: code-box +``` sql +WITH dublin_airport AS ( + SELECT + wkb_geometry + FROM + ne.airports_eu + WHERE + name = 'Dublin Airport' +) + + SELECT + name + FROM + dublin_airport a, + ne.airports_eu b + WHERE + ST_DWithin(a.wkb_geometry, b.wkb_geometry, 50*1000); +``` +::: + +Note how the letters a and b are used as aliases in the query. Aliases replace the names of different columns. Using them makes it easier to write and interpret queries, especially longer ones. You can read more about aliases here: [postgresql-alias](https://www.postgresqltutorial.com/postgresql-alias/). + +Which rivers are entirely contained inside one country? + +::: code-box +``` sql +SELECT +... +FROM +... +WHERE +... +``` +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +b.name_en +FROM +ne.countries_eu a, ne.rivers_eu b +WHERE +ST_...(a.wkb_geometry, b.wkb_geometry); +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +b.name_en +FROM +ne.countries_eu a, ne.rivers_eu b +WHERE +ST_Contains(a.wkb_geometry, b.wkb_geometry); +``` +::: +::: + +::: hint-box +Note! Of course, more countries than seen in the result contain entire rivers. The result seen here is because the Natural Earth river data set does not include all rivers, only major ones. +::: + +If you add the DISTINCT parameter to the SELECT command, you can find out how many countries entirely contain rivers. + +::: code-box +``` sql +SELECT + +FROM +(SELECT DISTINCT + +FROM + +WHERE +ST_Contains(..., ...)); +``` +::: + + + +::: hidden-box +::: code-box +``` sql +-- use a subquery and give it an alias +SELECT +count(country_distinct) +FROM +(SELECT DISTINCT +a.name_en as country_distinct +FROM +ne.countries_eu a, ne.rivers_eu b +WHERE +ST_...(... , ... )) AS country_distinct; +``` +::: +::: + + + +::: hidden-box +::: code-box +``` sql +SELECT +count(country_distinct) +FROM +(SELECT DISTINCT +a.name_en as country_distinct +FROM +ne.countries_eu a, ne.rivers_eu b +WHERE +ST_Contains(a.wkb_geometry, b.wkb_geometry)) as DistincKunta; +``` +::: +::: + +## Exercise 6.2 + +Which countries in the EU have more than 100 airports? + +::: code-box +``` sql +SELECT ... +``` +::: + + + +::: hidden-box +::: code-box +``` sql +-- Option 1 - Use a CTE +WITH apm AS ( +SELECT DISTINCT +a.name_en, COUNT(...) OVER(PARTITION BY ...) AS CountAirports +FROM +ne.countries_eu a, ne.airports_eu b +WHERE +contains(a.wkb_geometry, b.wkb_geometry) +ORDER BY +CountAirports DESC +) + +SELECT +name_en as "Country", countairports AS "Count of Airports" +FROM +apm +WHERE +CountAirports > 100; +``` +::: + +::: code-box +``` sql +-- Option 2 + +SELECT +a.name_en as "Country", count(...) as "Count" +FROM +ne.countries_eu a, ne.airports_Eu b +WHERE +contains(a.wkb_geometry, b.wkb_geometry) +GROUP BY +a.name_en +HAVING count(...) > ...; + +-- fill in the blanks. Choose the correct function +``` +::: +::: + +Thorough solution: + + + +::: hidden-box +::: code-box +``` sql +WITH apm AS ( +SELECT DISTINCT +a.name_en, COUNT(a.name_en) OVER(PARTITION BY a.name_en) AS CountAirports +FROM +ne.countries_eu a, ne.airports_eu b +WHERE +ST_Contains(a.wkb_geometry, b.wkb_geometry) +ORDER BY +CountAirports DESC +) + +SELECT +name_en as "Country", countairports AS "Count of Airports" +FROM +apm +WHERE +CountAirports > 100; +``` +::: +::: + +Simpler solution: + + + +::: hidden-box +::: code-box +``` sql +SELECT +a.name_en as "Country", count(*) as "Count" +FROM +ne.countries_eu a, ne.airports_Eu b +WHERE +ST_Contains(a.wkb_geometry, b.wkb_geometry) +GROUP BY +a.name_en +HAVING count(*) > 100; +``` +::: +::: + +## Exercise 6.3 + +Let's find the EU countries that have no railroads: + +::: code-box +``` sql +SELECT +b.name_en +FROM +(SELECT + ST_union(wkb_geometry) as wkb_geometry + FROM + ne.railroads_eu) as a, ne.countries_eu b +WHERE +ST_Disjoint(a.wkb_geometry, b.wkb_geometry); +``` +::: + +## Exercise 6.4 + +Let's find the three nearest airports. + +Using the K Nearest Neighbours method (KNN) you can find the three closest airports to a city point. + +::: code-box +``` sql +WITH madrid AS +(SELECT + wkb_geometry + FROM + ne.capitals_eu + WHERE + name_en = 'Madrid') + +SELECT +round(ST_Distance(madrid.wkb_geometry, a.wkb_geometry)/1000) as "km",* +FROM +ne.airports_eu a, madrid +ORDER BY +madrid.wkb_geometry <-> a.wkb_geometry +LIMIT 3; +``` +::: + +The same result can be achieved without the KNN algorithm: + +::: code-box +``` sql +SELECT +*, round(ST_Distance(wkb_geometry,( + SELECT ST_Centroid(wkb_geometry) + FROM + ne.capitals_eu + WHERE + name_en ='Madrid'))/1000) as distance +FROM +ne.airports_eu +ORDER by +distance +LIMIT 3; +``` +::: + +## Exercise 6.5 + +What are the neighbouring countires of the Czech Republic? + +::: code-box +``` sql +SELECT +b.name_en +FROM +(SELECT + name_en, wkb_geometry + FROM + ne.countries_eu + WHERE + name_en = 'Czech Republic') a, ne.countries_eu b +WHERE +ST_Touches(a.wkb_geometry, b.wkb_geometry); +``` +::: + +## Exercise 6.6 + +Find the rivers which cross over countries' borders: + +::: code-box +``` sql +SELECT +a.name_en, a.wkb_geometry +FROM +ne.rivers_eu a, ne.countries_eu b +WHERE +ST_Crosses(a.wkb_geometry, b.wkb_geometry) +``` +::: + +For visualizing results you can create a **new schema** (tmp). You can create a new table based on query results. QGIS can be used to visualize the results. You can also create a view from the results, but remember to add a **DISTINCT** identifier to the rows. + +::: code-box +``` sql +CREATE SCHEMA IF NOT EXISTS tmp; +``` +::: + +::: code-box +``` sql +DROP TABLE IF EXISTS tmp.crossrivers; + +CREATE TABLE tmp.crossrivers AS +( + SELECT + a.name_en, a.wkb_geometry + FROM + ne.rivers_eu a, ne.countries_eu b + WHERE + ST_Crosses(a.wkb_geometry, b.wkb_geometry) +); +``` +::: + +::: code-box +``` sql +DROP VIEW IF EXISTS tmp.view_crossrivers; + +CREATE VIEW tmp.view_crossrivers AS +( + SELECT DISTINCT + a.name_en, a.wkb_geometry, a.fid + FROM + ne.rivers_eu a, ne.countries_eu b + WHERE + ST_Crosses(a.wkb_geometry, b.wkb_geometry) +); +``` +::: + +Which was faster, creating the table or the view? + +::: hint-box +How about viewing them in QGIS? Why? +::: + +## Exercise 6.7 + +Let's calculate the minimum distance from Ireland's airports to the nearest railroad: + +::: code-box +``` sql +SELECT +a.name, MIN(ST_Distance(a.wkb_geometry, b.wkb_geometry)) as "dist" +FROM +ne.airports_eu a, ne.railroads_eu b +WHERE +a.country = 'Ireland' +GROUP BY +a.name +ORDER BY +dist; +``` +::: diff --git a/src/GS009_eng/07_exercise_7.Rmd b/src/GS009_eng/07_exercise_7.Rmd new file mode 100644 index 00000000..8e2785ef --- /dev/null +++ b/src/GS009_eng/07_exercise_7.Rmd @@ -0,0 +1,339 @@ +# Exercise 7: Spatial Reference Systems + +**Contents** -- In this exercise we explore how Spatial Reference Systems and map projections are processed in PostGIS. + +**Goal** -- The goal of the exercise is to understand the basics of using SRSs and map projections in PostGIS. + +### Preparation + +Open [pgAdmin](/pgadmin) in the browser and log in. Open the **Query Tool** (Right click *trainingdatabase* **-\>** **Query Tool**). + +### Functions + +In this exercise you can use for example the following functions +for coordinate conversions and transformations: + +| PostGIS function | Returns | +|:--: | :---: | +| ST_GeomFromText(text WKT, integer srid) | A ST_Geometry object from the OGC Well-Known text (WKT) representation with the given EPSG | +| ST_AsText(geometry g) | A human-readable WKT representation of an ST_Geometry object | +| ST_Transform(geometry g1, integer srid) | A geometry with its coordinates transformed to the spatial reference system given as a parameter as an EPSG code | +| ST_Transform(geometry geom, text to_proj) | A geometry with its coordinates transformed to a different spatial reference system given as a parameter in PROJ.4 format | +| ST_Transform(geometry geom, text from_proj, text to_proj) | A geometry with its coordinates transformed from a spatial reference system given as a parameter in PROJ.4 format to another spatial reference system given as a parameter in PROJ.4 format | +| ST_Transform(geometry geom, text from_proj, integer to_srid) | A geometry with its coordinates transformed from a spatial reference system given as a parameter in PROJ.4 format to another spatial reference system given as an EPSG code | + +## Exercise 7.1: Creating a geometry + +The goal is to execute a conversion for the coordinates of the Royal Observatory Greenwich from geographic coordinates (EPSG:4258) to the ETRS89-extended / LAEA Europe (EPSG:3035) coordinates. First create a PostGIS point for the observatory from these coordinates: 0.0005 (longitude) 51.4768 (latitude). + +:::code-box +```sql +SELECT +ST_AsText(ST_GeomFromText('POINT(0.0005 51.4769)', 4258)); +``` +::: + +## Exercise 7.2: Coordinate conversion + +Perform a coordinate conversion for the Greenwich Observatory coordinates to the ETRS89-extended /LAEA Europe (EPSG:3035) CRS using the **ST_Transform** function. + +:::code-box +```sql +SELECT +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- fill in the correct functions based on the hints +-- fill in the source and target CRS codes into the places marked with '...' +SELECT +ST_AsText(ST_...(ST_GeomFromText('POINT(0.0005 51.4769)', ...), ...)); +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +ST_AsText(ST_Transform(ST_GeomFromText('POINT(0.0005 51.4769)', 4258), 3035)); +``` +::: +::: + +The result should be as follows (as WKB): + +:::code-box +``` +0101000020DB0B0000BCB381E2A76848416523239D78AF4B41 +``` +::: + +or as text: + +:::code-box +``` +POINT(3199311.7695831936 3628785.2276348346) +``` +::: + +## Exercise 7.3: Another conversion + +Next let's perform a conversion for the same coordinates to the WGS 84 / Pseudo-Mercator (EPSG:3857) CRS. + +:::code-box +```sql +SELECT +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- fill in the correct function +-- fill in the target and source CRS codes +SELECT +ST_AsText(ST_...(ST_GeomFromText('POINT(0.0005 51.4769)', ...), ...)); +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +ST_AsText(ST_Transform(ST_GeomFromText('POINT(0.0005 51.4769)', 4258), 3857)); +``` +::: +::: + +The result should be: + +:::code-box +``` +POINT(55.65974539663679 6706089.334791817) +``` +::: + +## Exercise 7.4: SRS definitions + +You can find the definitions for different SRSs from the **spatial_ref_sys** table: + +:::code-box +```sql +SELECT +srid, proj4text +FROM +spatial_ref_sys +WHERE +srid = 4326; +``` +::: + +## Exercise 7.5: Comparing spatial reference system definitions + +What is the difference between the EPSG:4326 and EPSG:4258 SRSs? + +:::code-box +```sql +SELECT +... +FROM +... +WHERE +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- Select based on the EPSG code +SELECT +..., proj4text +FROM +spatial_ref_sys +WHERE +... in (4326, 4258); +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +srid, proj4text +FROM +spatial_ref_sys +WHERE +srid in (4326, 4258); +``` +::: +::: + +## Exercise 7.6: Creating a new spatial data table + +Let's create a new table with a geometry column with the WGS84 SRS. Let's create four columns in total (gid, name, ICAO, geom): + +:::code-box +```sql +DROP TABLE IF EXISTS air_geom; + +CREATE TABLE air_geom +( + gid serial PRIMARY KEY, + name varchar(254), + ICAO varchar(254), + geom geometry(Point,4326) +); +``` +::: + +Let's insert data from the previously created 'airports' table to the new 'air_geom' table. +Form the SELECT query first to make sure the insertion will be successful. + +:::code-box +```sql +INSERT INTO +air_geom(geom, name, ICAO) +SELECT +ST_GeomFromText('POINT(' || airports.longitude|| ' ' || airports.latitude||')',4326), +airports.name, airports.icao_code +FROM +airports; +``` +::: + +Using two vertical bar (pipe) symbols ```||``` you can concatenate text. + +## Exercise 7.7: Adding another geometry column + +Let's add another geometry column to the table, this time with the EPSG:3857 SRS: + +:::code-box +```sql +ALTER TABLE +air_geom +ADD COLUMN +geom3857 geometry(Point,3857); +``` +::: + +## Exercise 7.8: Saving converted geometries + +Let's convert and update new points to the new column: + +:::code-box +```sql +UPDATE +air_geom +SET +geom3857 = ST_Transform(geom, 3857); +``` +::: + +If running the command resulted in an error, how can you fix the issue? + +Explore the airport data set and find the row which causes the error. You can check what area the EPSG:3857 SRS covers, for example [here](https://epsg.io/3857). + +:::code-box +```sql +SELECT ... +FROM +... +WHERE +... +``` +::: + + + +::: hidden-box +:::code-box +```sql +SELECT * +FROM +air_geom +WHERE +y-coordinate(geom) < ...; + +-- Using which PostGIS can you return the Y coordinate? +-- fill in an appropriate Y value in the blank +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT * +FROM +air_geom +WHERE +ST_Y(geom) < -85.06; +``` +::: +::: + +When you have identified the problem, fix it by filtering out the problematic row: + +:::code-box +```sql +SELECT gid,name,icao,ST_asText(geom) +FROM air_geom +WHERE ST_Y(geom) = -90; +``` +::: + + + +::: hidden-box +:::code-box +```sql +UPDATE air_geom +SET geom3857 = ST_Transform(geom,3857) +WHERE ...; +-- filter out the problematic row +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT gid,name,icao,ST_asText(geom) +FROM air_geom +WHERE ST_Y(geom) = -90; +``` +::: +:::code-box +```sql +UPDATE air_geom +SET geom3857 = ST_Transform(geom,3857) +WHERE icao != 'NZSP'; +``` +::: +::: + +After you've fixed the problem, check the results using QGIS. diff --git a/src/GS009_eng/08_exercise_8.Rmd b/src/GS009_eng/08_exercise_8.Rmd new file mode 100644 index 00000000..2bcfffc1 --- /dev/null +++ b/src/GS009_eng/08_exercise_8.Rmd @@ -0,0 +1,310 @@ +# Exercise 8: Geoprocessing + +**Contents** -- In this exercise we explore the geoprocessing functions in PostGIS. + +**Goal** -- The goal of the exercise is to understand the basics of using geoprocessing functions. + +### Preparation + +Open [pgAdmin](/pgadmin) in the browser and log in. Open the **Query Tool** (Right click *trainingdatabase* **-\>** **Query Tool**). + +## Exercise 8.1: Centroids + +Run the following command: + +:::code-box +```sql +SELECT +ST_Centroid(wkb_geometry) as "Centroids of first 10" +FROM +ne.countries_eu +LIMIT 10; +``` +::: + +As a result we get the centroids of the first ten countries. + +## Exercise 8.2: Centroids within polygons + +Are all of the centroids inside the polygons? How many points are outside? + +:::code-box +```sql +SELECT ... +``` +::: + +Note that you can also get the same result by selecting the countries whose centroid is outside the polygon and counting the resulting rows. + + + +::: hidden-box +:::code-box +```sql +-- option 1 ST_Contains function +-- CTE:llä +WITH notin AS( + SELECT + ... + FROM + ... + WHERE + NOT ... + +SELECT +count(...) +FROM +notin; +``` +::: + +:::code-box +```sql +-- option 2 - ST_Within function +SELECT +... +FROM +... +WHERE +NOT ...; +``` +::: +::: + +Solution 1 (using the **ST_Contains** function): + + + +:::hidden-box +:::code-box +```sql +WITH notin AS( + SELECT + name_en as "withST_Contains" + FROM + ne.countries_eu + WHERE + NOT ST_Contains(wkb_geometry, ST_Centroid(wkb_geometry))) + +SELECT +count(notin."withST_Contains") +FROM +notin; +``` +::: +::: + +Solution 2 (Using the **ST_Within** function): + + + +:::hidden-box +:::code-box +```sql +SELECT +name_en as "with ST_Within" +FROM +ne.countries_eu +WHERE +NOT ST_Within(ST_Centroid(wkb_geometry), wkb_geometry); +``` +::: +::: + +## Exercise 8.3: Distances + +How much do the centroids found in exercise 8.1 differ from the results from the **ST_PointOnSurface** function, i.e. what are the distances between them? + +:::code-box +```sql +SELECT +... +FROM +... +WHERE +NOT ...; +``` +::: + + + +::: hidden-box +:::code-box +```sql +-- What function can you use to calculate distance between points? +SELECT +name_en as "Country", +round(ST_...(ST_PointOnSurface(wkb_geometry), ST_centroid(wkb_geometry))) +as "Distance PntOnSurface and Centroid" +FROM +ne.countries_eu +WHERE +NOT ...; +-- filter out points which are not inside of polygons. +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +SELECT +name_en as "Country", +round(ST_Distance(ST_PointOnSurface(wkb_geometry), ST_centroid(wkb_geometry))) +as "Distance PntOnSurface and Centroid" +FROM +ne.countries_eu +WHERE +NOT ST_Within(ST_Centroid(wkb_geometry), wkb_geometry); +``` +::: +::: + +## Exercise 8.4: Buffers + +Let's create a buffer for Sweden's railroads: + +:::code-box +```sql +SELECT +id, ST_Buffer(wkb_geometry, 100) as wkb_geometry +FROM +ne.railroads_eu +WHERE +country = 'Sweden'; +``` +::: + +Create a view of the buffers and visualize them in QGIS. You can create several buffers with different distances. Make sure to select the railroads of a certain country (f.e. Sweden). + +:::code-box +```sql +DROP VIEW IF EXISTS ne.view_railroadbuffer; + +CREATE VIEW ne.view_railroadbuffer AS ( + WITH buffers AS ( + ... + WHERE + country = 'Sweden' + UNION + ... + WHERE + country = 'Sweden' + ) + SELECT + row_number() OVER() AS vid, geom, buffer + FROM + buffers +); +``` +::: + + + +::: hidden-box +:::code-box +```sql +DROP VIEW IF EXISTS ne.view_railroadbuffer; + +CREATE VIEW ne.view_railroadbuffer AS ( + WITH buffers AS ( + SELECT + ..., 100 as buffer -- use the ST_Buffer function + FROM + ne.railroads_eu + WHERE + country = 'Sweden' + UNION + SELECT + ..., 250 as buffer -- use the ST_Buffer function + FROM + ne.railroads_eu + WHERE + country = 'Sweden' + ) + SELECT + row_number() OVER() AS vid, geom, buffer + FROM + buffers +); +``` +::: +::: + + + +:::hidden-box +:::code-box +```sql +DROP VIEW IF EXISTS ne.view_railroadbuffer; + +CREATE VIEW ne.view_railroadbuffer AS ( + WITH buffers AS ( + SELECT + ST_Buffer(wkb_geometry, 100) as geom, 100 as buffer + FROM + ne.railroads_eu + WHERE + country = 'Sweden' + UNION + SELECT + ST_Buffer(wkb_geometry, 250) as geom, 250 as buffer + FROM + ne.railroads_eu + WHERE + country = 'Sweden' + ) + SELECT + row_number() OVER() AS vid, geom, buffer + FROM + buffers +); +``` +::: +::: + +## Exercise 8.5: Union + +Combine the rivers of each country to it's own table: + +:::code-box +```sql +DROP TABLE IF EXISTS tmp.rivers_by_country; + +CREATE TABLE tmp.rivers_by_country as ( + SELECT + ST_Union(wkb_geometry), name_en_2 as "Country" + FROM + ne.rivers_eu + GROUP BY + name_en_2 +); +``` +::: + +You can also use views: + +:::code-box +```sql +DROP VIEW IF EXISTS tmp.view_riversbycountry; + +CREATE VIEW tmp.view_riversbycountry AS ( + SELECT + ST_Union(wkb_geometry), name_en_2 + FROM + ne.rivers_eu + GROUP BY + name_en_2 +); +``` +::: + +### PostGIS is efficient + +One of the major advantages of useing PostGIS is its efficiency in processing large data sets. + +#### Additional exercise + +Most of the geoprocessing tools can also be found in QGIS. The efficiency of PostGIS can be seen if you try to perform the same operation using the same tool in QGIS and PostGIS. Do you notice the difference? diff --git a/src/GS009_eng/09_exercise_09.Rmd b/src/GS009_eng/09_exercise_09.Rmd new file mode 100644 index 00000000..dd061117 --- /dev/null +++ b/src/GS009_eng/09_exercise_09.Rmd @@ -0,0 +1,229 @@ +# Exercise 9: PostgreSQL administration + +**Contents** -- Topics relating to PostgreSQL administration. + +**Goal** -- After the exercise the trainee knows some basics concepts of PostgreSQL administration. + +### Preparation + +Open [pgAdmin](/pgadmin) in the browser and log in. Open the **Query Tool** (Right click _trainingdatabase_ **->** **Query Tool**). + +## Exercise 9.1: Tablespaces + +Check the location of the training database server's default tablespaces. User information is located in the **pg_default** tablespace which is in the data_directory's base folder. General information about the system is located in the **pg_global** tablespace, which is in the data_directory's global folder. You can check the location of the data directory with the following command: + +:::code-box +```sql +SHOW data_directory; +``` +::: + +## Exercise 9.2: Database roles + +By default PostgreSQL has a role called 'postgres' and a database by the same name. In the prior exercises we've created a database to use in the training (_trainingdatabase_). You can create a new user in the database server with the following SQL command: + +:::code-box +```sql +DROP ROLE IF EXISTS matt; + +CREATE ROLE +matt +LOGIN PASSWORD +'1234' +CREATEDB +VALID UNTIL +'infinity'; +``` +::: + +The **CREATEDB** parameter defines the privilege to create databases for the user. The VALID parameter defines how long the role is valid for (in this case indefinitely). + +Create a new administrator role with the following SQL command: + +:::code-box +```sql +DROP ROLE IF EXISTS dba; + +CREATE ROLE +dba +LOGIN PASSWORD +'1234' +SUPERUSER +VALID UNTIL +'2027-1-1 00:00'; +``` +::: + +This new role has administrator privileges (SUPERUSER) and is valid until January 1st, 2027 +You can inspect the role's attributes with pgAdmin in the **Login/Group Roles** section (in the side panel). + +## Exercise 9.3: Group roles + +Group roles can be created with the following command: + +:::code-box +```sql +DROP ROLE IF EXISTS admins; + +CREATE ROLE +admins +INHERIT; +``` +::: + +The INHERIT parameter means that every role inside the **admins** group inherit the privileges of the group. As an exception the **SUPERUSER** privilege is never inherited in PostgreSQL. + +Add the `matt` and `dpa` roles to the `admins` group with this command: + +:::code-box +```sql +GRANT +admins +TO +matt, dba; +``` +::: + +You can switch roles with the **SET ROLE** command: + +:::code-box +```sql +SET ROLE +matt; +``` +::: + +You can check the currently used role with this command: + +::: code-box +```sql +SELECT current_user; +``` +::: + +Test the `SELECT session_user` command. + +:::code-box +```sql +SELECT ... +``` +::: + +:::hint-box +What is the difference between current_user and session_user? +::: + +## Exercise 9.4: Adding roles in the GUI + +![](img/pgadminrooli.png) + +Managing roles is easier in the pgAdmin user interface. Add a new user, choose a password and also add them to the admins group role. Note the SQL statement generated in the SQL tab. +Roles can be deleted with the **DROP ROLE < role_name >** command. + +## Exercise 9.5: Creating a new tablespace + +To create a new tablespace a folder must be created in the server. The folder must be owned by the postgres user and have permissions only for the postgres user. A folder has already been created to the training database server with the following commands: + +Create a new tablespace with the following command either in pgAdmin or psql: + +:::code-box +```sql +CREATE TABLESPACE tmp_tablespace +LOCATION '/usr/local/tmp_tbls'; +``` +::: + +## Exercise 9.6: Changing the tablespace of a database or a table + +You can alter the tablespace of an entire database with a single command. + +:::hint-box +**NOTE!** In order to do this the database **cannot** have any active connections! +::: + +1. Close the pgAdmin database connection to the _trainingdatabase_ by right clicking the database in the side panel and clicking **Disconnect Database**. +2. Open the _postgres_ database from the side panel and open the **Query Tool** (you can also do this in psql). Execute the following command: + +:::code-box +```sql +ALTER DATABASE trainingdatabase +SET TABLESPACE tmp_tablespace; +``` +::: + +:::hint-box +If this doesn't work and pgAdmin gives an error about active connections, try logging out and back into pgAdmin. +::: + +You can check the database's tablespace with this query: + +:::code-box +```sql +SELECT +spcname, pg_tablespace_location(oid) +FROM +pg_tablespace; +``` +::: + +For testing purposes create a temporary table: + +:::code-box +```sql +DROP TABLE IF EXISTS tmp_table; + +CREATE TABLE tmp_table AS +SELECT x +FROM +generate_series(2,5000,2) AS x; +``` +::: + +You can check which tablespace a table uses with this command: + +:::code-box +```sql +SELECT +tablename, tablespace +FROM +pg_tables +WHERE +tablename = 'tmp_table'; +``` +::: + +Alter the table's tablespace with the following command: + +:::code-box +```sql +ALTER TABLE +tmp_table +SET TABLESPACE +tmp_tablespace; +``` +::: + +Check that the tablespace of the `tmp_table` has been changed. You can also use pgAdmin's GUI to check tablespaces. + +## Exercise 9.7: Altering the tablespace of an index + +You can create an index for a table with this command: + +:::code-box +```sql +CREATE INDEX +idx_tmp_x +ON tmp_table(x); +``` +::: + +Indices are created in the **pg_default** tablespace by default. Often the indices should be saved to a tablespace which uses the server's fastest disk (e.g. SSD). You can change an index's tablespace with the following command: + +:::code-box +```sql +ALTER INDEX +idx_tmp_x +SET TABLESPACE +tmp_tablespace; +``` +::: diff --git a/src/GS009_eng/10_exercise_10.Rmd b/src/GS009_eng/10_exercise_10.Rmd new file mode 100644 index 00000000..1406ddc4 --- /dev/null +++ b/src/GS009_eng/10_exercise_10.Rmd @@ -0,0 +1,41 @@ +# Exercise 10: Creating and restoring backups + +**Contents** -- Introduction to creating and restoring database backups. + +**Goal** -- After the exercise the trainee knows how to create and restore a backup. + +## Exercise 10.1: Creating a backup + +Let's create a backup of the _trainingdatabase_ with pgAdmin. Right click the trainingdatabase and click **Backup...** + +![](img/pgadminback.png) + +:::hint-box +If the Backup window doesn't open and instead you get an error message, do the following: File > Preferences > on the left side choose Paths > Binary Paths and write **/usr/bin** in the PostgreSQL Binary Path field. +::: + +Fill the filename in the **Backup** window as **"trainingdatabase_backup"**. Make sure the format is **Tar** and the encoding is **UTF8**. + +![](img/pgadminback2.png) + +## Exercise 10.2: Restoring a database + +### Create a new database + +Right click your connection to the database cluster and click **Create > Database...**. Name the new database **"trainingdatabase2"**. + +![](img/pgadmindb2.png) + +### Restore the data from the backup file + +Let's restore the back up by right clicking the **trainingdatabase2** you just created. Choose **Restore... > Filename > ...** and choose the .tar file you just saved. + +![](img/pgadminrestore.png) + +If you can't find the backup file, set the **Format** to **All Files** in the bottom right corner of the **Select file** window. You can inspect the features which will be restored before the restoration takes place with the **Display Object** feature. + +![](img/pgadmindisplay.png) + +:::hint-box +How can you copy the structure (schema) of the trainingdatabase to another database? +::: diff --git a/src/GS009_eng/404.html b/src/GS009_eng/404.html new file mode 100644 index 00000000..2cc9f4b4 --- /dev/null +++ b/src/GS009_eng/404.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +Page not found | yaml_title_replace + + + + + + + + + + + + + + + + +
+ + + +
+ +
+
+ +
+
+
+
+
+

Page not found

+

The page you requested cannot be found (perhaps it was moved or renamed).

+

You may want to try searching to find the page's new location, or use +the table of contents to find the page you are looking for.

+
+

+

+
+
+ +
+ + +
+ +
+ + + + + + + diff --git a/src/GS009_eng/css/bootstrap.min.css b/src/GS009_eng/css/bootstrap.min.css new file mode 100644 index 00000000..8ceefe5e --- /dev/null +++ b/src/GS009_eng/css/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;/* flex:0 0 100%; */max-width:100%;}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem)}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 0%;flex:1 1 0%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:no-repeat 50%/50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal .list-group-item.active{margin-top:0}.list-group-horizontal .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm .list-group-item.active{margin-top:0}.list-group-horizontal-sm .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md .list-group-item.active{margin-top:0}.list-group-horizontal-md .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg .list-group-item.active{margin-top:0}.list-group-horizontal-lg .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl .list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl .list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl .list-group-item.active{margin-top:0}.list-group-horizontal-xl .list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl .list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush .list-group-item{border-right-width:0;border-left-width:0;border-radius:0}.list-group-flush .list-group-item:first-child{border-top-width:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}a.close.disabled{pointer-events:none}.toast{max-width:350px;overflow:hidden;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem)}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:no-repeat 50%/100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;-webkit-animation:spinner-border .75s linear infinite;animation:spinner-border .75s linear infinite}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner-grow .75s linear infinite;animation:spinner-grow .75s linear infinite}.spinner-grow-sm{width:1rem;height:1rem}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;overflow-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/src/GS009_eng/css/hamburgers.css b/src/GS009_eng/css/hamburgers.css new file mode 100644 index 00000000..8e49de35 --- /dev/null +++ b/src/GS009_eng/css/hamburgers.css @@ -0,0 +1,93 @@ +/*! + * Hamburgers + * @description Tasty CSS-animated hamburgers + * @author Jonathan Suh @jonsuh + * @site https://jonsuh.com/hamburgers + * @link https://github.com/jonsuh/hamburgers + */ +.hamburger { + padding: 15px 15px; + display: inline-block; + cursor: pointer; + transition-property: opacity, filter; + transition-duration: 0.15s; + transition-timing-function: linear; + font: inherit; + color: inherit; + text-transform: none; + background-color: transparent; + border: 0; + margin: 0; + overflow: visible; } + .hamburger:hover { + opacity: 0.7; } + .hamburger.is-active:hover { + opacity: 0.7; } + .hamburger.is-active .hamburger-inner, + .hamburger.is-active .hamburger-inner::before, + .hamburger.is-active .hamburger-inner::after { + background-color: #fbfbfb; } + +.hamburger-box { + width: 40px; + height: 24px; + display: inline-block; + position: relative; } + +.hamburger-inner { + display: block; + top: 50%; + margin-top: -2px; } + .hamburger-inner, .hamburger-inner::before, .hamburger-inner::after { + width: 40px; + height: 4px; + background-color: #000; + border-radius: 4px; + position: absolute; + transition-property: transform; + transition-duration: 0.15s; + transition-timing-function: ease; } + .hamburger-inner::before, .hamburger-inner::after { + content: ""; + display: block; } + .hamburger-inner::before { + top: -10px; } + .hamburger-inner::after { + bottom: -10px; } + +/* + * Arrow + */ +.hamburger--arrow.is-active .hamburger-inner::before { + transform: translate3d(-8px, 0, 0) rotate(-45deg) scale(0.7, 1); } + +.hamburger--arrow.is-active .hamburger-inner::after { + transform: translate3d(-8px, 0, 0) rotate(45deg) scale(0.7, 1); } + +/* + * Collapse + */ +.hamburger--collapse .hamburger-inner { + top: auto; + bottom: 0; + transition-duration: 0.13s; + transition-delay: 0.13s; + transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); } + .hamburger--collapse .hamburger-inner::after { + top: -20px; + transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1), opacity 0.1s linear; } + .hamburger--collapse .hamburger-inner::before { + transition: top 0.12s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1), transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19); } + +.hamburger--collapse.is-active .hamburger-inner { + transform: translate3d(0, -10px, 0) rotate(-45deg); + transition-delay: 0.22s; + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); } + .hamburger--collapse.is-active .hamburger-inner::after { + top: 0; + opacity: 0; + transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333), opacity 0.1s 0.22s linear; } + .hamburger--collapse.is-active .hamburger-inner::before { + top: 0; + transform: rotate(-90deg); + transition: top 0.1s 0.16s cubic-bezier(0.33333, 0, 0.66667, 0.33333), transform 0.13s 0.25s cubic-bezier(0.215, 0.61, 0.355, 1); } diff --git a/src/GS009_eng/custom.css b/src/GS009_eng/custom.css new file mode 100644 index 00000000..5062cb1d --- /dev/null +++ b/src/GS009_eng/custom.css @@ -0,0 +1,508 @@ +/* Import fonts */ +@import url("https://fonts.googleapis.com/css2?family=Karla:wght@300;400;700&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;700;800&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@300;400;700&display=swap"); +@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"); + + +/* to-do */ +.todo { + background-color: red; + color:#eeeeee; +} + + +.in-view { + background-color: #ab8b9b; + + padding-left: 3%; + padding-top: 2%; + padding-bottom: 2%; + padding-right: 10%; + + border-radius: 0.5em; +} + +/* Generics */ +body { overflow-x: hidden; } + +p, span, li { + color: #434662; + font-family: 'Karla', sans-serif; + font-size: 1em !important; + text-align: left; + line-height: 1.6em !important; +} + +a { + color: #936287 !important; + text-decoration: underline !important; + background-color: transparent; +} + +a:hover { + color: #caabbe !important; + text-decoration: underline; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Inter', sans-serif !important; + font-weight: bold !important; + color: #434662; + line-height: 140%; + margin-bottom: 0.6em !important; + margin-top: 1em !important; +} + +h1 { font-size: 240% !important; } + +h2 { font-size: 200% !important; } + +h3 { font-size: 160% !important; } + +h4 { font-size: 120% !important; } + +h5 { font-size: 100% !important; } + +/* Sidebar and toc */ + +.sidebar { + background-color: #7a3884; + color: #fbfbfb; + position: fixed; + top: 0; + left: 0; + bottom: 0; + z-index: 100; + width: 20%; + overflow-y: visible; +} + +.sidebar-wrapper { + padding: 5% 10%; + width: 100%; + height: 100%; + overflow: scroll; +} + +.sidebar-wrapper::-webkit-scrollbar { + width: 0 !important; + background: transparent !important; +} + +.sidebar-title-wrapper { + margin: 10% 5% 20% 5%; +} + +.sidebar-title { + text-align: left !important; +} + +.sidebar-title h1 { + color: #fbfbfb !important; +} + +.sidebar-title:after { + content: ""; + background: #fbfbfb; + height: 0.01em; + width: auto; + display: block; + margin-top: 2em; + margin-bottom: 2em; +} + +.sidebar-logo { + display: block; + margin-bottom: 1.8em; +} + +.abstract-sidebar p { + color: #fbfbfb; + font-size: 90%; +} + +.sidebar-nav { + margin: 0; +} + +.sidebar .navbar-toggle { + display: none; +} + +#TOC ul { + position: relative; + padding-inline-start: 6%; +} + +#TOC li { + list-style: none; + padding-bottom: 0.6em; +} + +#TOC > ul > li > a { + height: auto; + font-family: 'Inter', sans-serif; + font-size: 120%; + font-weight: bold; + padding-bottom: 0.6em; + text-decoration: none !important; +} + +#TOC li > a { + color: #fbfbfb !important; + width: 100%; + max-width: 300px; + display: flex; + align-items: flex-start; + flex-direction: row; + justify-content: flex-start; + font-family: 'Inter', sans-serif; + text-decoration: none !important; +} + +#TOC li > a:hover { text-decoration: underline !important; } + +.toc-section-number { + color: inherit; + padding-right: 0.4em; + margin-bottom: 0.2em !important; + display: none; +} + +/* Main content */ + +.main-content { + background-color: #fff; + display: flex; + position: relative; + min-height: 100vh; + height: auto; + width: auto; + justify-content: space-between; + flex-direction: column; + align-items: stretch; +} + +.header-section-number { + display: none; +} + +.main-content-wrapper { padding-bottom: 15%; } + +.level1 { /* wraps around main content */ + flex: 1 0 auto; + justify-content: space-between; + margin-left: 20%; + padding: 2em 3em; + max-width: 60%; + height: auto; +} +.level1 img { + max-width: 100%; + padding: 1em 0; +} + +.level1 .figure { padding: 1em 0; } + +.level1 p, .level1 span { margin-bottom: 1rem !important; } + +/* Title */ + +#title-container { + text-align: left; + margin-left: 20%; + padding: 2em 3em; +} + +#title-container:after { + content: ""; + background: #434662; + display: block; + position: relative; + height: 0.01em; + width: auto; + margin-top: 2em; +} + +/* Tables */ + +table .header { + background-color: #7a3884; + color: #fbfbfb !important; +} + +table .odd { + background-color: #FCFCFC; +} + +table .even { + background-color: #F5F5F5; +} + +table th, +table td { + border-right: 1px solid #ffffff; + padding: 0.8em; + font-family: 'Karla', sans-serif; +} + +/* Buttons */ + +.btn { + font-weight: bold !important; + font-family: 'Inter', sans-serif; + color: #fbfbfb !important; + background-color: #7a3884 !important; + border: none !important; + margin: 0.8em 0.8em !important; + padding: 0.4em 0.8em !important; + border-radius: 3 !important; + display:block +} + +.btn:hover { + color: #fbfbfb !important; + text-decoration: none; + background-color: #ab8b9b !important; +} + +.copy-button { + visibility: hidden; + position: absolute; + top: 0px; + right: 0px; + width: 2.5rem; + height: 2.5rem; + padding: 5px; + background-color: transparent; + border: 1px solid #434662; + border-radius: 3px; + cursor: pointer; + } + +.copy-button{ + color: #8588a2; +} + +.copy-button:hover{ + color: #434662; +} + +.copy-button::before { + font-family: "Font Awesome 5 Free"; + font-weight: 900; + content: "\f0c5"; + } + +.copy-button.show-checkmark::before { + content: "\f00c"; + color:#0f9400; +} + +.code-box:hover .copy-button, +.commandline-box:hover .copy-button { + visibility: visible; + } + + +/* Footer */ + +.footer { + display: flex; + position: absolute; + bottom: 0; + width: 100%; + height: auto; + padding-top: 4em; + padding-bottom: 2em; + flex-shrink: 0; + margin: 0; + flex-direction: column; + align-items: flex-end; +} + +.footer:before { + content: ""; + background-image: url(img/Gispo_tausta.png); + background-repeat: no-repeat; + background-size: cover; + display: block; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0.4; + z-index: 1; + clip-path: polygon(0 10%, 20% 15%, 40% 35%, 54% 20%, 66% 40%, 78% 10%, 85% 15%, 90% 0%, 100% 0, 100% 100%, 0 100%); +} + +.footer-container { + display: flex; + align-items: flex-start; + justify-content: space-around; + z-index: 2; +} + +.footer-info { + padding: 0 1.6em; + text-align: right; +} + +.footer-version { position: relative; } + +.license { padding-top: 10%; } + +.footer-contact { + margin: 0 20px; +} +.footer-contact-info { + display: block; + text-align: right; +} + +.footer-copyright-year { font-size: 0.5rem; } + +/* Content boxes */ + +.hint-box { + background: #434662; + padding: 10px; + border: none; + margin-bottom: 1rem; + border-radius: 3px; +} + +.hint-box p { + color: #fbfbfb; + margin: 0 !important; +} + +.note-box { + background: #ffffff; + padding: 10px; + border: none; + margin-bottom: 1rem; + border-radius: 3px; +} + +.note-box p { + color: #434662; + margin: 0 !important; +} + +.code-box { + position: relative; + background: #f5d2cc; + padding-top: 0.1rem; + padding-bottom: 0.1rem; + padding-left: 1rem; + padding-right: 1rem; + border: none; + display: flex; + align-items: center; + margin-bottom: 1rem; + min-height: 2.5rem; + border-radius: 3px; +} + +code span { + font-family: 'Source Code Pro', monospace; +} + +.code-box p { + color: #000000; + font-family: 'Source Code Pro', sans-serif !important; + margin: 0 !important; +} + +.file-content-box { + background: #caabbe; + padding: 10px; + border: none; + margin-bottom: 1rem; + border-radius: 3px; +} + +.file-content-box p { + color: #000000; + margin: 0 !important; +} + +.commandline-box { + position: relative; + background: #cccccc; + padding-top: 0.1rem; + padding-bottom: 0.1rem; + padding-left: 1rem; + padding-right: 1rem; + border: none; + display: flex; + align-items: center; + margin-bottom: 1rem; + min-height: 2.5rem; + border-radius: 3px; +} + +.commandline-box p { + font-family: 'Source Code Pro', monospace; + color: #000000; + margin: 0 !important; +} + +.hidden-box { + display: none; + padding: 1rem; + background: #f0f0f079; +} + +/* Media queries */ +@media (max-width: 1540px) { + .sidebar { width: 320px; } + .main-content-wrapper { padding-bottom: 200px; } + #title-container { margin-left: 320px; } + .level1 { + margin-left: 320px; + width: calc(100% - 320px); + } +} + +@media (max-width: 1199px) and (min-width: 992px) { .level1 { padding: 80px 40px 25px; } } + +/* Hide sidebar */ +@media (max-width: 991px) { + .sidebar { + width: 320px; + left: -320px; + transition: all 0.3s ease; + } + + .sidebar.show { left: 0; } + .sidebar-wrapper { padding: 15px; } + + .sidebar .navbar-toggle { + display: inline-block; + position: fixed; + left: 20px; + padding: 10px 15px; + transition: all 0.3s ease; + border-radius: 0; + outline: none; + } + + + #title-container { margin-left: 0; } + .level1 { + margin-left: 0; + padding: 50px 40px; + width: 100%; + max-width: none; + } + .footer { margin-left: 0; } +} + +@media (max-width: 767px) { + .level1 { padding: 60px 10px; } +} + diff --git a/src/GS009_eng/custom.html b/src/GS009_eng/custom.html new file mode 100644 index 00000000..cf990842 --- /dev/null +++ b/src/GS009_eng/custom.html @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + +$if(url)$$endif$ +$if(cover-image)$$endif$ +$if(description)$$endif$ +$if(github-repo)$$endif$ + +$for(author-meta)$ + +$endfor$ + +$if(date-meta)$ + +$endif$ + +$if(math)$ + +$math$ +$endif$ + + + +$if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ + +$for(header-includes)$ +$header-includes$ +$endfor$ + +$if(highlightjs)$ + + + + +$endif$ + +$if(highlighting-css)$ + + +$endif$ + +$for(css)$ + +$endfor$ + + + + + + + + +$for(include-before)$ +$include-before$ +$endfor$ + +
+ + + +
+ + + +
+ +$if(title)$ +

$title$

+$if(subtitle)$ +

$subtitle$

+$endif$ + +$for(author)$ +$if(author.name)$ +

$author.name$

+ +$if(author.affiliation)$ +
$author.affiliation$
+$endif$ + +$if(author.email)$ +$author.email$
+$endif$ +$else$ +

$author$

+$endif$ +$endfor$ + +$if(date)$ +

Version: $date$

+$endif$ + +$if(abstract)$ +

$abstract$

+$endif$ + +$endif$ +
+ + + + + + + +$body$ + + +
+ + +
+ +
+ +$for(include-after)$ +$include-after$ +$endfor$ + + + + + + diff --git a/src/GS009_eng/img/Gispo_tausta.png b/src/GS009_eng/img/Gispo_tausta.png new file mode 100644 index 00000000..9a59898d Binary files /dev/null and b/src/GS009_eng/img/Gispo_tausta.png differ diff --git a/src/GS009_eng/img/JHSsuositus.png b/src/GS009_eng/img/JHSsuositus.png new file mode 100644 index 00000000..81a2e475 Binary files /dev/null and b/src/GS009_eng/img/JHSsuositus.png differ diff --git a/src/GS009_eng/img/batchrun.png b/src/GS009_eng/img/batchrun.png new file mode 100644 index 00000000..3cf3daf3 Binary files /dev/null and b/src/GS009_eng/img/batchrun.png differ diff --git a/src/GS009_eng/img/by-nd.svg b/src/GS009_eng/img/by-nd.svg new file mode 100644 index 00000000..6efd00d8 --- /dev/null +++ b/src/GS009_eng/img/by-nd.svg @@ -0,0 +1,203 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/GS009_eng/img/createdb.png b/src/GS009_eng/img/createdb.png new file mode 100644 index 00000000..61f1a475 Binary files /dev/null and b/src/GS009_eng/img/createdb.png differ diff --git a/src/GS009_eng/img/gispo_white.png b/src/GS009_eng/img/gispo_white.png new file mode 100644 index 00000000..6bd5633c Binary files /dev/null and b/src/GS009_eng/img/gispo_white.png differ diff --git a/src/GS009_eng/img/gispo_white_sm.png b/src/GS009_eng/img/gispo_white_sm.png new file mode 100644 index 00000000..678ab928 Binary files /dev/null and b/src/GS009_eng/img/gispo_white_sm.png differ diff --git a/src/GS009_eng/img/gispologosvg.svg b/src/GS009_eng/img/gispologosvg.svg new file mode 100644 index 00000000..1a0bfada --- /dev/null +++ b/src/GS009_eng/img/gispologosvg.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/GS009_eng/img/open_terminal.gif b/src/GS009_eng/img/open_terminal.gif new file mode 100644 index 00000000..9ee6e0c2 Binary files /dev/null and b/src/GS009_eng/img/open_terminal.gif differ diff --git a/src/GS009_eng/img/paikkatietoikkuna.png b/src/GS009_eng/img/paikkatietoikkuna.png new file mode 100644 index 00000000..f79674f3 Binary files /dev/null and b/src/GS009_eng/img/paikkatietoikkuna.png differ diff --git a/src/GS009_eng/img/pgadmin_create_server.gif b/src/GS009_eng/img/pgadmin_create_server.gif new file mode 100644 index 00000000..fc5deaea Binary files /dev/null and b/src/GS009_eng/img/pgadmin_create_server.gif differ diff --git a/src/GS009_eng/img/pgadmin_geom.png b/src/GS009_eng/img/pgadmin_geom.png new file mode 100644 index 00000000..50aed6b6 Binary files /dev/null and b/src/GS009_eng/img/pgadmin_geom.png differ diff --git a/src/GS009_eng/img/pgadmin_query_tool.gif b/src/GS009_eng/img/pgadmin_query_tool.gif new file mode 100644 index 00000000..3600d973 Binary files /dev/null and b/src/GS009_eng/img/pgadmin_query_tool.gif differ diff --git a/src/GS009_eng/img/pgadmin_splash.png b/src/GS009_eng/img/pgadmin_splash.png new file mode 100644 index 00000000..09a2d18b Binary files /dev/null and b/src/GS009_eng/img/pgadmin_splash.png differ diff --git a/src/GS009_eng/img/pgadminback.png b/src/GS009_eng/img/pgadminback.png new file mode 100644 index 00000000..f3104dd2 Binary files /dev/null and b/src/GS009_eng/img/pgadminback.png differ diff --git a/src/GS009_eng/img/pgadminback2.png b/src/GS009_eng/img/pgadminback2.png new file mode 100644 index 00000000..1b1cd680 Binary files /dev/null and b/src/GS009_eng/img/pgadminback2.png differ diff --git a/src/GS009_eng/img/pgadmindb2.png b/src/GS009_eng/img/pgadmindb2.png new file mode 100644 index 00000000..65083b05 Binary files /dev/null and b/src/GS009_eng/img/pgadmindb2.png differ diff --git a/src/GS009_eng/img/pgadmindbluo.png b/src/GS009_eng/img/pgadmindbluo.png new file mode 100644 index 00000000..b32b1e6d Binary files /dev/null and b/src/GS009_eng/img/pgadmindbluo.png differ diff --git a/src/GS009_eng/img/pgadmindbluo2.png b/src/GS009_eng/img/pgadmindbluo2.png new file mode 100644 index 00000000..0d87dc5d Binary files /dev/null and b/src/GS009_eng/img/pgadmindbluo2.png differ diff --git a/src/GS009_eng/img/pgadmindisplay.png b/src/GS009_eng/img/pgadmindisplay.png new file mode 100644 index 00000000..63bbe220 Binary files /dev/null and b/src/GS009_eng/img/pgadmindisplay.png differ diff --git a/src/GS009_eng/img/pgadminrestore.png b/src/GS009_eng/img/pgadminrestore.png new file mode 100644 index 00000000..cec2b434 Binary files /dev/null and b/src/GS009_eng/img/pgadminrestore.png differ diff --git a/src/GS009_eng/img/pgadminrooli.png b/src/GS009_eng/img/pgadminrooli.png new file mode 100644 index 00000000..9acdcea4 Binary files /dev/null and b/src/GS009_eng/img/pgadminrooli.png differ diff --git a/src/GS009_eng/img/pgadminylapalkki.png b/src/GS009_eng/img/pgadminylapalkki.png new file mode 100644 index 00000000..c7274d98 Binary files /dev/null and b/src/GS009_eng/img/pgadminylapalkki.png differ diff --git a/src/GS009_eng/img/pgadylapalkki.png b/src/GS009_eng/img/pgadylapalkki.png new file mode 100644 index 00000000..c5aab82e Binary files /dev/null and b/src/GS009_eng/img/pgadylapalkki.png differ diff --git a/src/GS009_eng/img/psql_start.png b/src/GS009_eng/img/psql_start.png new file mode 100644 index 00000000..63693bf4 Binary files /dev/null and b/src/GS009_eng/img/psql_start.png differ diff --git a/src/GS009_eng/img/qgisDbmanager.png b/src/GS009_eng/img/qgisDbmanager.png new file mode 100644 index 00000000..7bdd6a93 Binary files /dev/null and b/src/GS009_eng/img/qgisDbmanager.png differ diff --git a/src/GS009_eng/img/qgis_add_data.png b/src/GS009_eng/img/qgis_add_data.png new file mode 100644 index 00000000..1a194efe Binary files /dev/null and b/src/GS009_eng/img/qgis_add_data.png differ diff --git a/src/GS009_eng/img/qgis_batch_load.png b/src/GS009_eng/img/qgis_batch_load.png new file mode 100644 index 00000000..ded9683a Binary files /dev/null and b/src/GS009_eng/img/qgis_batch_load.png differ diff --git a/src/GS009_eng/img/qgis_pg_connection.png b/src/GS009_eng/img/qgis_pg_connection.png new file mode 100644 index 00000000..b1dd7546 Binary files /dev/null and b/src/GS009_eng/img/qgis_pg_connection.png differ diff --git a/src/GS009_eng/img/qgislayers.png b/src/GS009_eng/img/qgislayers.png new file mode 100644 index 00000000..7bd56623 Binary files /dev/null and b/src/GS009_eng/img/qgislayers.png differ diff --git a/src/GS009_eng/img/run_cell.gif b/src/GS009_eng/img/run_cell.gif new file mode 100644 index 00000000..3d7788f8 Binary files /dev/null and b/src/GS009_eng/img/run_cell.gif differ diff --git a/src/GS009_eng/index.Rmd b/src/GS009_eng/index.Rmd new file mode 100644 index 00000000..5e2d2a02 --- /dev/null +++ b/src/GS009_eng/index.Rmd @@ -0,0 +1,34 @@ +--- +title: "Introduction to PostGIS" +author: "Gispo Ltd" +date: "`r Sys.Date()`" +site: "bookdown::bookdown_site" +abstract: "Introduction to typical PostGIS use cases." +output: + bookdown::html_book: + toc: true + toc_depth: 2 + number_sections: true + pandoc_args: ["--number-sections"] + theme: null + template: custom.html + css: custom.css + split_by: rmd + +documentclass: book +--- + +# 1. Introduction + +Welcome to the exercise section of the course! + +With these exercises you can learn how to use the PostGIS extension in the PostgreSQL database management system. Choose a topic from the panel to the left. + +## 1.1 Training material license + +These training materials have been published with the [Create Commons Attribution-NoDerivs 4.0](https://creativecommons.org/licenses/by-nd/4.0/) license. + +Licenses for the data used in the exercises: + +- airports.dat - downloaded from [Openflights](https://openflights.org/data.html). The airport data is in the public domain. +- [Natural Earth](https://www.naturalearthdata.com/) - Data is in the public domain. Used data sets are: airports, countries, railroads, capitals and rivers (1:10m). Most data sets have been modified to include only EU countries. Some data sets have been slightly modified (fields which are unnecessary in the training have been removed or changed and some overseas territories of countries have been deleted as they warped certain analysis results. diff --git a/src/GS009_eng/index.html b/src/GS009_eng/index.html new file mode 100644 index 00000000..2d254291 --- /dev/null +++ b/src/GS009_eng/index.html @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +yaml_title_replace + + + + + + + + + + + + + + + + +
+ + + +
+ +
+
+ +
+
+
+
+ +
+ +

yaml_title_replace

+ +

Gispo author_replace

+ +

Version: 2024-09-24

+ +

abstract_replace

+ +
+ +
+

document_title_replace

+
+

Kurssimateriaalien lataaminen

+

Voit ladata harjoituksissa käytettävän kurssihakemiston tästä linkistä:

+ +
+
+

Lukuohje

+

Web-selaimessa suoritettavat komennot on merkitty seuraavasti:

+ +

Komentorivillä suoritettavat komennot on merkitty seuraavasti:

+
+
sudo lsb_release -a
+
+

Tiedostojen sisältö on esitetty seuraavasti:

+
+

#IPv4 local connections: #host all all 127.0.0.1/32 md5

+
+

HTML- ja CSS-koodit, SQL-komennot sekä Python-scriptit on esitetty seuraavasti:

+
+
SELECT version();
+
+

Kysymykset, lisätiedot ja vihjeet on esitetty seuraavasti:

+
+

Mistä löydät tietoa GeoServeristä?

+

GeoServerillä on omat kotisivut.

+

Psst! Tietoa GeoServeristä löydät internetistä.

+
+
+
+

Mistä lisätietoja?

+

Ohessa muutamia web-sivustoja, joista saat lisätietoja:

+ + + + +
+
+

Virheet

+

Jos havaitset materiaalissa virheitä, niin pyydämme ilmoittamaan niistä kouluttajalle tai sähköpostilla .

+
+
+

Lisenssi ja oikeudet

+

Nämä materiaalit on “license_title_replace”- kurssille kehittänyt Gispo Suomi Oy. Materiaalit on lisensoitu seuraavalla lisenssillä: CC BY-ND 4.0

+
+
+

+

+
+
+ +
+ + +
+ +
+ + + + + + + diff --git a/src/GS009_eng/js/answer-key.js b/src/GS009_eng/js/answer-key.js new file mode 100644 index 00000000..cf1c7ecd --- /dev/null +++ b/src/GS009_eng/js/answer-key.js @@ -0,0 +1,110 @@ +var hiddenBoxes = document.getElementsByClassName("hidden-box"); + +const filePath = window.location.pathname; + +const directoryName = filePath.substring(0, filePath.lastIndexOf('/')); + +let language; +if (directoryName.includes("_eng")) { + language = "EN"; +} else if (directoryName.includes("_sv")) { + language = "SV"; +} else { + language = "FI"; +} + +for (var i = 0; i < hiddenBoxes.length; i++) { + hiddenBoxes[i].id = "hidden-box-" + (i + 1); +} + +const codeBoxes = document.querySelectorAll('.code-box, .commandline-box'); + +codeBoxes.forEach(box => { + const copyButton = document.createElement('button'); + copyButton.className = 'copy-button'; + + copyButton.addEventListener('click', () => { + const text = box.innerText.trim(); + + navigator.clipboard.writeText(text) + .then(() => { + copyButton.classList.add('show-checkmark'); + setTimeout(() => { + copyButton.classList.remove('show-checkmark'); + }, 1000); + }) + .catch(err => { + console.error('Failed to copy text:', err); + }); + }); + + box.appendChild(copyButton); +}); + +let show; +let hide; +let next; +let previous; + +switch (language) { + case "EN": + show = "Show "; + hide = "Hide "; + next = "Next"; + previous = "Previous"; + break; + case "SV": + show = "Visa "; + hide = "Dölj "; + next = "Nästa"; + previous = "Tillbaka"; + break; + default: + show = "Näytä "; + hide = "Piilota "; + next = "Seuraava"; + previous = "Edellinen"; +} + +const navButtons = [...document.getElementsByClassName('btn-default')]; +navButtons.forEach(button => { + if (button.textContent === "Next") + { + button.textContent = next; + } + else if (button.textContent === "Previous") + { + button.textContent = previous; + } +}); + +const answerButtons = [...document.getElementsByClassName('answer_btn')]; +answerButtons.forEach(button => { + button.textContent = show + button.textContent; +}); + +function toggleAnswer(button) { + let buttons = document.getElementsByClassName('answer_btn'); + let buttonIndex = Array.from(buttons).indexOf(button) + 1; + + let buttonTextInput = button.textContent; + let words = buttonTextInput.split(" "); + let originalButtonText = words.slice(1).join(' '); + + let boxId = "hidden-box-" + buttonIndex; + let hiddenBox = document.getElementById(boxId); + + if (hiddenBox) { + let currentDisplay = window.getComputedStyle(hiddenBox).getPropertyValue("display"); + if (currentDisplay === "none") { + hiddenBox.style.display = "block"; + button.textContent = hide + originalButtonText; + } else { + hiddenBox.style.display = "none"; + button.textContent = show + originalButtonText; + } + } + else { + button.textContent = "ERROR: Could not find hidden-box"; + } +} diff --git a/src/GS009_eng/js/nav-script.js b/src/GS009_eng/js/nav-script.js new file mode 100644 index 00000000..c4aff29b --- /dev/null +++ b/src/GS009_eng/js/nav-script.js @@ -0,0 +1,74 @@ +function navToggle() { + let sidebar = document.getElementById('sidebar'); + sidebar.classList.toggle('show'); + let hamburger = document.querySelector('.hamburger') + hamburger.classList.toggle('is-active'); +} + +const sidebarLinks = document.querySelectorAll('.sidebar-nav a'); +const documentFileName = window.location.pathname.split('/').pop(); + +var matchingLinks = []; + +sidebarLinks.forEach(function(link) { + var linkHref = link.getAttribute('href').split('#')[0]; + var linkFileName = linkHref.split('/').pop(); + if (linkFileName === documentFileName) + matchingLinks.push(link); + +}); + + +const headers = document.querySelectorAll( + "h1:not(.sidebar-nav h1), " + + "h2, " + + "h3" +); + + +// Jump to to current document's title in the sidebar + +document.addEventListener('DOMContentLoaded', function() { + var pageTitle = document.title; + + var targetLink = null; + + matchingLinks.forEach(function(link) { + if (pageTitle.includes(link.textContent.trim())) + { + targetLink = link; + return; + } + }); + + if (targetLink) { + targetLink.classList.add('in-view'); + targetLink.scrollIntoView({ + behavior: 'instant', + block: 'center' + }); + } +}); + +// Highlight the header in the sidebar you're currently scrolling at in the main body + +window.addEventListener("scroll", () => { + headers.forEach((header) => { + const headerTop = header.offsetTop; + const headerHeight = header.clientHeight; + + if (scrollY >= (headerTop - 50) - headerHeight) + { + current = header; + } + + matchingLinks.forEach((link) => { + link.classList.remove("in-view"); + if (link.textContent == current.textContent) + { + link.classList.add('in-view'); + } + }); + }); +}); +