diff --git a/README.md b/README.md index 2ca504d..e83313a 100644 --- a/README.md +++ b/README.md @@ -194,4 +194,11 @@ server { proxy_cache_bypass $http_upgrade; } } -``` \ No newline at end of file +``` + +## Projects Sites +As I develope more projects I would like an easy way to add and host them on my website without having to create another subdomain and generate more ssl certs. I simply want the project site to be accessible under https://jrtechs.net/project_name. + +### State Diagrm of Plan + +![diagram](docs/projectsSites.svg) \ No newline at end of file diff --git a/blogContent/projects/steam/Diagram.svg b/blogContent/projects/steam/Diagram.svg new file mode 100644 index 0000000..ad8ce63 --- /dev/null +++ b/blogContent/projects/steam/Diagram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/blogContent/projects/steam/css/bootstrap.css b/blogContent/projects/steam/css/bootstrap.css new file mode 100644 index 0000000..eaed9ab --- /dev/null +++ b/blogContent/projects/steam/css/bootstrap.css @@ -0,0 +1,9647 @@ +/*! + * Bootswatch v4.1.1 + * Homepage: https://bootswatch.com + * Copyright 2012-2018 Thomas Park + * Licensed under MIT + * Based on Bootstrap +*/ +/*! + * Bootstrap v4.1.1 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +@import url("https://fonts.googleapis.com/css?family=Roboto:400,500,700"); +:root { + --blue: #325D88; + --indigo: #6610f2; + --purple: #6f42c1; + --pink: #e83e8c; + --red: #d9534f; + --orange: #F47C3C; + --yellow: #ffc107; + --green: #93C54B; + --teal: #20c997; + --cyan: #29ABE0; + --white: #fff; + --gray: #8E8C84; + --gray-dark: #3E3F3A; + --primary: #325D88; + --secondary: #8E8C84; + --success: #93C54B; + --info: #29ABE0; + --warning: #F47C3C; + --danger: #d9534f; + --light: #F8F5F0; + --dark: #3E3F3A; + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --font-family-sans-serif: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +*, +*::before, +*::after { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +html { + font-family: sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + -ms-overflow-style: scrollbar; + -webkit-tap-highlight-color: transparent; +} + +@-ms-viewport { + width: device-width; +} + +article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { + display: block; +} + +body { + margin: 0; + font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 0.875rem; + font-weight: 400; + line-height: 1.5; + color: #3E3F3A; + text-align: left; + background-color: #fff; +} + +[tabindex="-1"]:focus { + outline: 0 !important; +} + +hr { + -webkit-box-sizing: content-box; + box-sizing: content-box; + height: 0; + overflow: visible; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0.5rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-original-title] { + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: .5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +dfn { + font-style: italic; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +a { + color: #93C54B; + text-decoration: none; + background-color: transparent; + -webkit-text-decoration-skip: objects; +} + +a:hover { + color: #6b9430; + text-decoration: underline; +} + +a:not([href]):not([tabindex]) { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):focus { + outline: 0; +} + +pre, +code, +kbd, +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; + -ms-overflow-style: scrollbar; +} + +figure { + margin: 0 0 1rem; +} + +img { + vertical-align: middle; + border-style: none; +} + +svg:not(:root) { + overflow: hidden; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #8E8C84; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: 0.5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type="radio"], +input[type="checkbox"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} + +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + -webkit-appearance: listbox; +} + +textarea { + overflow: auto; + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: 1.5rem; + line-height: inherit; + color: inherit; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + outline-offset: -2px; + -webkit-appearance: none; +} + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +summary { + display: list-item; + cursor: pointer; +} + +template { + display: none; +} + +[hidden] { + display: none !important; +} + +h1, h2, h3, h4, h5, h6, +.h1, .h2, .h3, .h4, .h5, .h6 { + margin-bottom: 0.5rem; + font-family: inherit; + font-weight: 400; + line-height: 1.2; + color: inherit; +} + +h1, .h1 { + font-size: 2.1875rem; +} + +h2, .h2 { + font-size: 1.75rem; +} + +h3, .h3 { + font-size: 1.53125rem; +} + +h4, .h4 { + font-size: 1.3125rem; +} + +h5, .h5 { + font-size: 1.09375rem; +} + +h6, .h6 { + font-size: 0.875rem; +} + +.lead { + font-size: 1.09375rem; + 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, 0.1); +} + +small, +.small { + font-size: 80%; + font-weight: 400; +} + +mark, +.mark { + padding: 0.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: 0.5rem; +} + +.initialism { + font-size: 90%; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.09375rem; +} + +.blockquote-footer { + display: block; + font-size: 80%; + color: #8E8C84; +} + +.blockquote-footer::before { + content: "\2014 \00A0"; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: #fff; + border: 1px solid #DFD7CA; + border-radius: 0.25rem; + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 90%; + color: #8E8C84; +} + +code { + font-size: 87.5%; + color: #e83e8c; + word-break: break-word; +} + +a > code { + color: inherit; +} + +kbd { + padding: 0.2rem 0.4rem; + font-size: 87.5%; + color: #fff; + background-color: #212529; + border-radius: 0.2rem; +} + +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: 700; +} + +pre { + display: block; + font-size: 87.5%; + color: #212529; +} + +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +.container-fluid { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +.row { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -15px; + margin-left: -15px; +} + +.no-gutters { + margin-right: 0; + margin-left: 0; +} + +.no-gutters > .col, +.no-gutters > [class*="col-"] { + padding-right: 0; + padding-left: 0; +} + +.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, +.col-auto, .col-sm-1, .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-10, .col-sm-11, .col-sm-12, .col-sm, +.col-sm-auto, .col-md-1, .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-10, .col-md-11, .col-md-12, .col-md, +.col-md-auto, .col-lg-1, .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-10, .col-lg-11, .col-lg-12, .col-lg, +.col-lg-auto, .col-xl-1, .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-10, .col-xl-11, .col-xl-12, .col-xl, +.col-xl-auto { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} + +.col { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; +} + +.col-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; +} + +.col-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; +} + +.col-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; +} + +.col-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; +} + +.col-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; +} + +.col-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; +} + +.col-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; +} + +.col-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; +} + +.col-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; +} + +.col-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; +} + +.col-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; +} + +.col-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; +} + +.col-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; +} + +.order-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1; +} + +.order-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13; +} + +.order-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; +} + +.order-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; +} + +.order-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; +} + +.order-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; +} + +.order-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; +} + +.order-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; +} + +.order-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; +} + +.order-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7; +} + +.order-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8; +} + +.order-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9; +} + +.order-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10; +} + +.order-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11; +} + +.order-12 { + -webkit-box-ordinal-group: 13; + -ms-flex-order: 12; + order: 12; +} + +.offset-1 { + margin-left: 8.3333333333%; +} + +.offset-2 { + margin-left: 16.6666666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.3333333333%; +} + +.offset-5 { + margin-left: 41.6666666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.3333333333%; +} + +.offset-8 { + margin-left: 66.6666666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.3333333333%; +} + +.offset-11 { + margin-left: 91.6666666667%; +} + +@media (min-width: 576px) { + .col-sm { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-sm-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-sm-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; + } + .col-sm-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; + } + .col-sm-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-sm-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; + } + .col-sm-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; + } + .col-sm-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-sm-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; + } + .col-sm-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; + } + .col-sm-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-sm-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; + } + .col-sm-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; + } + .col-sm-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-sm-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1; + } + .order-sm-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13; + } + .order-sm-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; + } + .order-sm-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; + } + .order-sm-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; + } + .order-sm-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; + } + .order-sm-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; + } + .order-sm-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; + } + .order-sm-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; + } + .order-sm-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7; + } + .order-sm-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8; + } + .order-sm-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9; + } + .order-sm-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10; + } + .order-sm-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11; + } + .order-sm-12 { + -webkit-box-ordinal-group: 13; + -ms-flex-order: 12; + order: 12; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.3333333333%; + } + .offset-sm-2 { + margin-left: 16.6666666667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.3333333333%; + } + .offset-sm-5 { + margin-left: 41.6666666667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.3333333333%; + } + .offset-sm-8 { + margin-left: 66.6666666667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.3333333333%; + } + .offset-sm-11 { + margin-left: 91.6666666667%; + } +} + +@media (min-width: 768px) { + .col-md { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-md-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-md-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; + } + .col-md-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; + } + .col-md-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-md-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; + } + .col-md-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; + } + .col-md-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-md-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; + } + .col-md-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; + } + .col-md-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-md-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; + } + .col-md-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; + } + .col-md-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-md-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1; + } + .order-md-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13; + } + .order-md-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; + } + .order-md-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; + } + .order-md-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; + } + .order-md-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; + } + .order-md-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; + } + .order-md-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; + } + .order-md-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; + } + .order-md-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7; + } + .order-md-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8; + } + .order-md-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9; + } + .order-md-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10; + } + .order-md-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11; + } + .order-md-12 { + -webkit-box-ordinal-group: 13; + -ms-flex-order: 12; + order: 12; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.3333333333%; + } + .offset-md-2 { + margin-left: 16.6666666667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.3333333333%; + } + .offset-md-5 { + margin-left: 41.6666666667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.3333333333%; + } + .offset-md-8 { + margin-left: 66.6666666667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.3333333333%; + } + .offset-md-11 { + margin-left: 91.6666666667%; + } +} + +@media (min-width: 992px) { + .col-lg { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-lg-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-lg-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; + } + .col-lg-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; + } + .col-lg-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-lg-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; + } + .col-lg-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; + } + .col-lg-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-lg-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; + } + .col-lg-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; + } + .col-lg-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-lg-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; + } + .col-lg-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; + } + .col-lg-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-lg-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1; + } + .order-lg-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13; + } + .order-lg-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; + } + .order-lg-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; + } + .order-lg-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; + } + .order-lg-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; + } + .order-lg-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; + } + .order-lg-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; + } + .order-lg-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; + } + .order-lg-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7; + } + .order-lg-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8; + } + .order-lg-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9; + } + .order-lg-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10; + } + .order-lg-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11; + } + .order-lg-12 { + -webkit-box-ordinal-group: 13; + -ms-flex-order: 12; + order: 12; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.3333333333%; + } + .offset-lg-2 { + margin-left: 16.6666666667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.3333333333%; + } + .offset-lg-5 { + margin-left: 41.6666666667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.3333333333%; + } + .offset-lg-8 { + margin-left: 66.6666666667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.3333333333%; + } + .offset-lg-11 { + margin-left: 91.6666666667%; + } +} + +@media (min-width: 1200px) { + .col-xl { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-xl-auto { + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-xl-1 { + -webkit-box-flex: 0; + -ms-flex: 0 0 8.3333333333%; + flex: 0 0 8.3333333333%; + max-width: 8.3333333333%; + } + .col-xl-2 { + -webkit-box-flex: 0; + -ms-flex: 0 0 16.6666666667%; + flex: 0 0 16.6666666667%; + max-width: 16.6666666667%; + } + .col-xl-3 { + -webkit-box-flex: 0; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-xl-4 { + -webkit-box-flex: 0; + -ms-flex: 0 0 33.3333333333%; + flex: 0 0 33.3333333333%; + max-width: 33.3333333333%; + } + .col-xl-5 { + -webkit-box-flex: 0; + -ms-flex: 0 0 41.6666666667%; + flex: 0 0 41.6666666667%; + max-width: 41.6666666667%; + } + .col-xl-6 { + -webkit-box-flex: 0; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-xl-7 { + -webkit-box-flex: 0; + -ms-flex: 0 0 58.3333333333%; + flex: 0 0 58.3333333333%; + max-width: 58.3333333333%; + } + .col-xl-8 { + -webkit-box-flex: 0; + -ms-flex: 0 0 66.6666666667%; + flex: 0 0 66.6666666667%; + max-width: 66.6666666667%; + } + .col-xl-9 { + -webkit-box-flex: 0; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-xl-10 { + -webkit-box-flex: 0; + -ms-flex: 0 0 83.3333333333%; + flex: 0 0 83.3333333333%; + max-width: 83.3333333333%; + } + .col-xl-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 91.6666666667%; + flex: 0 0 91.6666666667%; + max-width: 91.6666666667%; + } + .col-xl-12 { + -webkit-box-flex: 0; + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-xl-first { + -webkit-box-ordinal-group: 0; + -ms-flex-order: -1; + order: -1; + } + .order-xl-last { + -webkit-box-ordinal-group: 14; + -ms-flex-order: 13; + order: 13; + } + .order-xl-0 { + -webkit-box-ordinal-group: 1; + -ms-flex-order: 0; + order: 0; + } + .order-xl-1 { + -webkit-box-ordinal-group: 2; + -ms-flex-order: 1; + order: 1; + } + .order-xl-2 { + -webkit-box-ordinal-group: 3; + -ms-flex-order: 2; + order: 2; + } + .order-xl-3 { + -webkit-box-ordinal-group: 4; + -ms-flex-order: 3; + order: 3; + } + .order-xl-4 { + -webkit-box-ordinal-group: 5; + -ms-flex-order: 4; + order: 4; + } + .order-xl-5 { + -webkit-box-ordinal-group: 6; + -ms-flex-order: 5; + order: 5; + } + .order-xl-6 { + -webkit-box-ordinal-group: 7; + -ms-flex-order: 6; + order: 6; + } + .order-xl-7 { + -webkit-box-ordinal-group: 8; + -ms-flex-order: 7; + order: 7; + } + .order-xl-8 { + -webkit-box-ordinal-group: 9; + -ms-flex-order: 8; + order: 8; + } + .order-xl-9 { + -webkit-box-ordinal-group: 10; + -ms-flex-order: 9; + order: 9; + } + .order-xl-10 { + -webkit-box-ordinal-group: 11; + -ms-flex-order: 10; + order: 10; + } + .order-xl-11 { + -webkit-box-ordinal-group: 12; + -ms-flex-order: 11; + order: 11; + } + .order-xl-12 { + -webkit-box-ordinal-group: 13; + -ms-flex-order: 12; + order: 12; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.3333333333%; + } + .offset-xl-2 { + margin-left: 16.6666666667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.3333333333%; + } + .offset-xl-5 { + margin-left: 41.6666666667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.3333333333%; + } + .offset-xl-8 { + margin-left: 66.6666666667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.3333333333%; + } + .offset-xl-11 { + margin-left: 91.6666666667%; + } +} + +.table { + width: 100%; + max-width: 100%; + margin-bottom: 1rem; + background-color: transparent; +} + +.table th, +.table td { + padding: 0.75rem; + vertical-align: top; + border-top: 1px solid #DFD7CA; +} + +.table thead th { + vertical-align: bottom; + border-bottom: 2px solid #DFD7CA; +} + +.table tbody + tbody { + border-top: 2px solid #DFD7CA; +} + +.table .table { + background-color: #fff; +} + +.table-sm th, +.table-sm td { + padding: 0.3rem; +} + +.table-bordered { + border: 1px solid #DFD7CA; +} + +.table-bordered th, +.table-bordered td { + border: 1px solid #DFD7CA; +} + +.table-bordered thead th, +.table-bordered thead td { + border-bottom-width: 2px; +} + +.table-borderless th, +.table-borderless td, +.table-borderless thead th, +.table-borderless tbody + tbody { + border: 0; +} + +.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(0, 0, 0, 0.05); +} + +.table-hover tbody tr:hover { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-primary, +.table-primary > th, +.table-primary > td { + background-color: #c6d2de; +} + +.table-hover .table-primary:hover { + background-color: #b6c5d5; +} + +.table-hover .table-primary:hover > td, +.table-hover .table-primary:hover > th { + background-color: #b6c5d5; +} + +.table-secondary, +.table-secondary > th, +.table-secondary > td { + background-color: #dfdfdd; +} + +.table-hover .table-secondary:hover { + background-color: #d3d3d0; +} + +.table-hover .table-secondary:hover > td, +.table-hover .table-secondary:hover > th { + background-color: #d3d3d0; +} + +.table-success, +.table-success > th, +.table-success > td { + background-color: #e1efcd; +} + +.table-hover .table-success:hover { + background-color: #d5e9ba; +} + +.table-hover .table-success:hover > td, +.table-hover .table-success:hover > th { + background-color: #d5e9ba; +} + +.table-info, +.table-info > th, +.table-info > td { + background-color: #c3e7f6; +} + +.table-hover .table-info:hover { + background-color: #addef3; +} + +.table-hover .table-info:hover > td, +.table-hover .table-info:hover > th { + background-color: #addef3; +} + +.table-warning, +.table-warning > th, +.table-warning > td { + background-color: #fcdac8; +} + +.table-hover .table-warning:hover { + background-color: #fbcab0; +} + +.table-hover .table-warning:hover > td, +.table-hover .table-warning:hover > th { + background-color: #fbcab0; +} + +.table-danger, +.table-danger > th, +.table-danger > td { + background-color: #f4cfce; +} + +.table-hover .table-danger:hover { + background-color: #efbbb9; +} + +.table-hover .table-danger:hover > td, +.table-hover .table-danger:hover > th { + background-color: #efbbb9; +} + +.table-light, +.table-light > th, +.table-light > td { + background-color: #fdfcfb; +} + +.table-hover .table-light:hover { + background-color: #f5efea; +} + +.table-hover .table-light:hover > td, +.table-hover .table-light:hover > th { + background-color: #f5efea; +} + +.table-dark, +.table-dark > th, +.table-dark > td { + background-color: #c9c9c8; +} + +.table-hover .table-dark:hover { + background-color: #bcbcbb; +} + +.table-hover .table-dark:hover > td, +.table-hover .table-dark:hover > th { + background-color: #bcbcbb; +} + +.table-active, +.table-active > th, +.table-active > td { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-hover .table-active:hover { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-hover .table-active:hover > td, +.table-hover .table-active:hover > th { + background-color: rgba(0, 0, 0, 0.075); +} + +.table .thead-dark th { + color: #fff; + background-color: #212529; + border-color: #32383e; +} + +.table .thead-light th { + color: #495057; + background-color: #F8F5F0; + border-color: #DFD7CA; +} + +.table-dark { + color: #fff; + background-color: #212529; +} + +.table-dark th, +.table-dark td, +.table-dark thead th { + border-color: #32383e; +} + +.table-dark.table-bordered { + border: 0; +} + +.table-dark.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(255, 255, 255, 0.05); +} + +.table-dark.table-hover tbody tr:hover { + background-color: rgba(255, 255, 255, 0.075); +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-sm > .table-bordered { + border: 0; + } +} + +@media (max-width: 767.98px) { + .table-responsive-md { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-md > .table-bordered { + border: 0; + } +} + +@media (max-width: 991.98px) { + .table-responsive-lg { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-lg > .table-bordered { + border: 0; + } +} + +@media (max-width: 1199.98px) { + .table-responsive-xl { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-xl > .table-bordered { + border: 0; + } +} + +.table-responsive { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; +} + +.table-responsive > .table-bordered { + border: 0; +} + +.form-control { + display: block; + width: 100%; + padding: 0.375rem 0.75rem; + font-size: 0.875rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + border-radius: 0.25rem; + -webkit-transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; +} + +@media screen and (prefers-reduced-motion: reduce) { + .form-control { + -webkit-transition: none; + transition: none; + } +} + +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} + +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #6f9dca; + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.25); + box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.25); +} + +.form-control::-webkit-input-placeholder { + color: #8E8C84; + opacity: 1; +} + +.form-control:-ms-input-placeholder { + color: #8E8C84; + opacity: 1; +} + +.form-control::-ms-input-placeholder { + color: #8E8C84; + opacity: 1; +} + +.form-control::placeholder { + color: #8E8C84; + opacity: 1; +} + +.form-control:disabled, .form-control[readonly] { + background-color: #F8F5F0; + opacity: 1; +} + +select.form-control:not([size]):not([multiple]) { + height: calc(2.0625rem + 2px); +} + +select.form-control:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.form-control-file, +.form-control-range { + display: block; + width: 100%; +} + +.col-form-label { + padding-top: calc(0.375rem + 1px); + padding-bottom: calc(0.375rem + 1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} + +.col-form-label-lg { + padding-top: calc(0.5rem + 1px); + padding-bottom: calc(0.5rem + 1px); + font-size: 1.09375rem; + line-height: 1.5; +} + +.col-form-label-sm { + padding-top: calc(0.25rem + 1px); + padding-bottom: calc(0.25rem + 1px); + font-size: 0.765625rem; + line-height: 1.5; +} + +.form-control-plaintext { + display: block; + width: 100%; + padding-top: 0.375rem; + padding-bottom: 0.375rem; + margin-bottom: 0; + line-height: 1.5; + color: #3E3F3A; + background-color: transparent; + border: solid transparent; + border-width: 1px 0; +} + +.form-control-plaintext.form-control-sm, .input-group-sm > .form-control-plaintext.form-control, +.input-group-sm > .input-group-prepend > .form-control-plaintext.input-group-text, +.input-group-sm > .input-group-append > .form-control-plaintext.input-group-text, +.input-group-sm > .input-group-prepend > .form-control-plaintext.btn, +.input-group-sm > .input-group-append > .form-control-plaintext.btn, .form-control-plaintext.form-control-lg, .input-group-lg > .form-control-plaintext.form-control, +.input-group-lg > .input-group-prepend > .form-control-plaintext.input-group-text, +.input-group-lg > .input-group-append > .form-control-plaintext.input-group-text, +.input-group-lg > .input-group-prepend > .form-control-plaintext.btn, +.input-group-lg > .input-group-append > .form-control-plaintext.btn { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm, .input-group-sm > .form-control, +.input-group-sm > .input-group-prepend > .input-group-text, +.input-group-sm > .input-group-append > .input-group-text, +.input-group-sm > .input-group-prepend > .btn, +.input-group-sm > .input-group-append > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.765625rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]), +.input-group-sm > .input-group-prepend > select.input-group-text:not([size]):not([multiple]), +.input-group-sm > .input-group-append > select.input-group-text:not([size]):not([multiple]), +.input-group-sm > .input-group-prepend > select.btn:not([size]):not([multiple]), +.input-group-sm > .input-group-append > select.btn:not([size]):not([multiple]) { + height: calc(1.6484375rem + 2px); +} + +.form-control-lg, .input-group-lg > .form-control, +.input-group-lg > .input-group-prepend > .input-group-text, +.input-group-lg > .input-group-append > .input-group-text, +.input-group-lg > .input-group-prepend > .btn, +.input-group-lg > .input-group-append > .btn { + padding: 0.5rem 1rem; + font-size: 1.09375rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]), +.input-group-lg > .input-group-prepend > select.input-group-text:not([size]):not([multiple]), +.input-group-lg > .input-group-append > select.input-group-text:not([size]):not([multiple]), +.input-group-lg > .input-group-prepend > select.btn:not([size]):not([multiple]), +.input-group-lg > .input-group-append > select.btn:not([size]):not([multiple]) { + height: calc(2.640625rem + 2px); +} + +.form-group { + margin-bottom: 1rem; +} + +.form-text { + display: block; + margin-top: 0.25rem; +} + +.form-row { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -5px; + margin-left: -5px; +} + +.form-row > .col, +.form-row > [class*="col-"] { + padding-right: 5px; + padding-left: 5px; +} + +.form-check { + position: relative; + display: block; + padding-left: 1.25rem; +} + +.form-check-input { + position: absolute; + margin-top: 0.3rem; + margin-left: -1.25rem; +} + +.form-check-input:disabled ~ .form-check-label { + color: #8E8C84; +} + +.form-check-label { + margin-bottom: 0; +} + +.form-check-inline { + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding-left: 0; + margin-right: 0.75rem; +} + +.form-check-inline .form-check-input { + position: static; + margin-top: 0; + margin-right: 0.3125rem; + margin-left: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #93C54B; +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: .5rem; + margin-top: .1rem; + font-size: .875rem; + line-height: 1; + color: #fff; + background-color: rgba(147, 197, 75, 0.8); + border-radius: .2rem; +} + +.was-validated .form-control:valid, .form-control.is-valid, .was-validated +.custom-select:valid, +.custom-select.is-valid { + border-color: #93C54B; +} + +.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated +.custom-select:valid:focus, +.custom-select.is-valid:focus { + border-color: #93C54B; + -webkit-box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.25); + box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.25); +} + +.was-validated .form-control:valid ~ .valid-feedback, +.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback, +.form-control.is-valid ~ .valid-tooltip, .was-validated +.custom-select:valid ~ .valid-feedback, +.was-validated +.custom-select:valid ~ .valid-tooltip, +.custom-select.is-valid ~ .valid-feedback, +.custom-select.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-control-file:valid ~ .valid-feedback, +.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback, +.form-control-file.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { + color: #93C54B; +} + +.was-validated .form-check-input:valid ~ .valid-feedback, +.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback, +.form-check-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label { + color: #93C54B; +} + +.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before { + background-color: #cde4ab; +} + +.was-validated .custom-control-input:valid ~ .valid-feedback, +.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback, +.custom-control-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { + background-color: #aad172; +} + +.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before { + -webkit-box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(147, 197, 75, 0.25); + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(147, 197, 75, 0.25); +} + +.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { + border-color: #93C54B; +} + +.was-validated .custom-file-input:valid ~ .custom-file-label::before, .custom-file-input.is-valid ~ .custom-file-label::before { + border-color: inherit; +} + +.was-validated .custom-file-input:valid ~ .valid-feedback, +.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback, +.custom-file-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { + -webkit-box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.25); + box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.25); +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #d9534f; +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: .5rem; + margin-top: .1rem; + font-size: .875rem; + line-height: 1; + color: #fff; + background-color: rgba(217, 83, 79, 0.8); + border-radius: .2rem; +} + +.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated +.custom-select:invalid, +.custom-select.is-invalid { + border-color: #d9534f; +} + +.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated +.custom-select:invalid:focus, +.custom-select.is-invalid:focus { + border-color: #d9534f; + -webkit-box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.25); + box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.25); +} + +.was-validated .form-control:invalid ~ .invalid-feedback, +.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback, +.form-control.is-invalid ~ .invalid-tooltip, .was-validated +.custom-select:invalid ~ .invalid-feedback, +.was-validated +.custom-select:invalid ~ .invalid-tooltip, +.custom-select.is-invalid ~ .invalid-feedback, +.custom-select.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-control-file:invalid ~ .invalid-feedback, +.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback, +.form-control-file.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { + color: #d9534f; +} + +.was-validated .form-check-input:invalid ~ .invalid-feedback, +.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback, +.form-check-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label { + color: #d9534f; +} + +.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before { + background-color: #f0b9b8; +} + +.was-validated .custom-control-input:invalid ~ .invalid-feedback, +.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback, +.custom-control-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { + background-color: #e27c79; +} + +.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before { + -webkit-box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(217, 83, 79, 0.25); + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(217, 83, 79, 0.25); +} + +.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { + border-color: #d9534f; +} + +.was-validated .custom-file-input:invalid ~ .custom-file-label::before, .custom-file-input.is-invalid ~ .custom-file-label::before { + border-color: inherit; +} + +.was-validated .custom-file-input:invalid ~ .invalid-feedback, +.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback, +.custom-file-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { + -webkit-box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.25); + box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.25); +} + +.form-inline { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.form-inline .form-check { + width: 100%; +} + +@media (min-width: 576px) { + .form-inline label { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + margin-bottom: 0; + } + .form-inline .form-group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin-bottom: 0; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-plaintext { + display: inline-block; + } + .form-inline .input-group, + .form-inline .custom-select { + width: auto; + } + .form-inline .form-check { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + width: auto; + padding-left: 0; + } + .form-inline .form-check-input { + position: relative; + margin-top: 0; + margin-right: 0.25rem; + margin-left: 0; + } + .form-inline .custom-control { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + } + .form-inline .custom-control-label { + margin-bottom: 0; + } +} + +.btn { + display: inline-block; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.25rem; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out; +} + +@media screen and (prefers-reduced-motion: reduce) { + .btn { + -webkit-transition: none; + transition: none; + } +} + +.btn:hover, .btn:focus { + text-decoration: none; +} + +.btn:focus, .btn.focus { + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.25); + box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.25); +} + +.btn.disabled, .btn:disabled { + opacity: 0.65; +} + +.btn:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active { + background-image: none; +} + +a.btn.disabled, +fieldset:disabled a.btn { + pointer-events: none; +} + +.btn-primary { + color: #fff; + background-color: #325D88; + border-color: #325D88; +} + +.btn-primary:hover { + color: #fff; + background-color: #284a6c; + border-color: #244463; +} + +.btn-primary:focus, .btn-primary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.5); + box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.5); +} + +.btn-primary.disabled, .btn-primary:disabled { + color: #fff; + background-color: #325D88; + border-color: #325D88; +} + +.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, +.show > .btn-primary.dropdown-toggle { + color: #fff; + background-color: #244463; + border-color: #213d59; +} + +.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-primary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.5); + box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.5); +} + +.btn-secondary { + color: #fff; + background-color: #8E8C84; + border-color: #8E8C84; +} + +.btn-secondary:hover { + color: #fff; + background-color: #7b7971; + border-color: #74726b; +} + +.btn-secondary:focus, .btn-secondary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(142, 140, 132, 0.5); + box-shadow: 0 0 0 0.2rem rgba(142, 140, 132, 0.5); +} + +.btn-secondary.disabled, .btn-secondary:disabled { + color: #fff; + background-color: #8E8C84; + border-color: #8E8C84; +} + +.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, +.show > .btn-secondary.dropdown-toggle { + color: #fff; + background-color: #74726b; + border-color: #6e6c65; +} + +.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-secondary.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(142, 140, 132, 0.5); + box-shadow: 0 0 0 0.2rem rgba(142, 140, 132, 0.5); +} + +.btn-success { + color: #fff; + background-color: #93C54B; + border-color: #93C54B; +} + +.btn-success:hover { + color: #fff; + background-color: #80b139; + border-color: #79a736; +} + +.btn-success:focus, .btn-success.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.5); + box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.5); +} + +.btn-success.disabled, .btn-success:disabled { + color: #fff; + background-color: #93C54B; + border-color: #93C54B; +} + +.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, +.show > .btn-success.dropdown-toggle { + color: #fff; + background-color: #79a736; + border-color: #729e33; +} + +.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-success.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.5); + box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.5); +} + +.btn-info { + color: #fff; + background-color: #29ABE0; + border-color: #29ABE0; +} + +.btn-info:hover { + color: #fff; + background-color: #1d95c6; + border-color: #1b8dbb; +} + +.btn-info:focus, .btn-info.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(41, 171, 224, 0.5); + box-shadow: 0 0 0 0.2rem rgba(41, 171, 224, 0.5); +} + +.btn-info.disabled, .btn-info:disabled { + color: #fff; + background-color: #29ABE0; + border-color: #29ABE0; +} + +.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, +.show > .btn-info.dropdown-toggle { + color: #fff; + background-color: #1b8dbb; + border-color: #1984b0; +} + +.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-info.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(41, 171, 224, 0.5); + box-shadow: 0 0 0 0.2rem rgba(41, 171, 224, 0.5); +} + +.btn-warning { + color: #fff; + background-color: #F47C3C; + border-color: #F47C3C; +} + +.btn-warning:hover { + color: #fff; + background-color: #f26418; + border-color: #ef5c0e; +} + +.btn-warning:focus, .btn-warning.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(244, 124, 60, 0.5); + box-shadow: 0 0 0 0.2rem rgba(244, 124, 60, 0.5); +} + +.btn-warning.disabled, .btn-warning:disabled { + color: #fff; + background-color: #F47C3C; + border-color: #F47C3C; +} + +.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, +.show > .btn-warning.dropdown-toggle { + color: #fff; + background-color: #ef5c0e; + border-color: #e3570d; +} + +.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-warning.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(244, 124, 60, 0.5); + box-shadow: 0 0 0 0.2rem rgba(244, 124, 60, 0.5); +} + +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d9534f; +} + +.btn-danger:hover { + color: #fff; + background-color: #d23430; + border-color: #c9302c; +} + +.btn-danger:focus, .btn-danger.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.5); + box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.5); +} + +.btn-danger.disabled, .btn-danger:disabled { + color: #fff; + background-color: #d9534f; + border-color: #d9534f; +} + +.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, +.show > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #c9302c; + border-color: #bf2e29; +} + +.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-danger.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.5); + box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.5); +} + +.btn-light { + color: #212529; + background-color: #F8F5F0; + border-color: #F8F5F0; +} + +.btn-light:hover { + color: #212529; + background-color: #ece4d6; + border-color: #e8decd; +} + +.btn-light:focus, .btn-light.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 245, 240, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 245, 240, 0.5); +} + +.btn-light.disabled, .btn-light:disabled { + color: #212529; + background-color: #F8F5F0; + border-color: #F8F5F0; +} + +.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, +.show > .btn-light.dropdown-toggle { + color: #212529; + background-color: #e8decd; + border-color: #e4d8c5; +} + +.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-light.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 245, 240, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 245, 240, 0.5); +} + +.btn-dark { + color: #fff; + background-color: #3E3F3A; + border-color: #3E3F3A; +} + +.btn-dark:hover { + color: #fff; + background-color: #2a2b28; + border-color: #242422; +} + +.btn-dark:focus, .btn-dark.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(62, 63, 58, 0.5); + box-shadow: 0 0 0 0.2rem rgba(62, 63, 58, 0.5); +} + +.btn-dark.disabled, .btn-dark:disabled { + color: #fff; + background-color: #3E3F3A; + border-color: #3E3F3A; +} + +.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, +.show > .btn-dark.dropdown-toggle { + color: #fff; + background-color: #242422; + border-color: #1d1e1b; +} + +.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-dark.dropdown-toggle:focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(62, 63, 58, 0.5); + box-shadow: 0 0 0 0.2rem rgba(62, 63, 58, 0.5); +} + +.btn-outline-primary { + color: #325D88; + background-color: transparent; + background-image: none; + border-color: #325D88; +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #325D88; + border-color: #325D88; +} + +.btn-outline-primary:focus, .btn-outline-primary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.5); + box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.5); +} + +.btn-outline-primary.disabled, .btn-outline-primary:disabled { + color: #325D88; + 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: #325D88; + border-color: #325D88; +} + +.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.5); + box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.5); +} + +.btn-outline-secondary { + color: #8E8C84; + background-color: transparent; + background-image: none; + border-color: #8E8C84; +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #8E8C84; + border-color: #8E8C84; +} + +.btn-outline-secondary:focus, .btn-outline-secondary.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(142, 140, 132, 0.5); + box-shadow: 0 0 0 0.2rem rgba(142, 140, 132, 0.5); +} + +.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { + color: #8E8C84; + 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: #8E8C84; + border-color: #8E8C84; +} + +.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(142, 140, 132, 0.5); + box-shadow: 0 0 0 0.2rem rgba(142, 140, 132, 0.5); +} + +.btn-outline-success { + color: #93C54B; + background-color: transparent; + background-image: none; + border-color: #93C54B; +} + +.btn-outline-success:hover { + color: #fff; + background-color: #93C54B; + border-color: #93C54B; +} + +.btn-outline-success:focus, .btn-outline-success.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.5); + box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.5); +} + +.btn-outline-success.disabled, .btn-outline-success:disabled { + color: #93C54B; + 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: #93C54B; + border-color: #93C54B; +} + +.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.5); + box-shadow: 0 0 0 0.2rem rgba(147, 197, 75, 0.5); +} + +.btn-outline-info { + color: #29ABE0; + background-color: transparent; + background-image: none; + border-color: #29ABE0; +} + +.btn-outline-info:hover { + color: #fff; + background-color: #29ABE0; + border-color: #29ABE0; +} + +.btn-outline-info:focus, .btn-outline-info.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(41, 171, 224, 0.5); + box-shadow: 0 0 0 0.2rem rgba(41, 171, 224, 0.5); +} + +.btn-outline-info.disabled, .btn-outline-info:disabled { + color: #29ABE0; + 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: #29ABE0; + border-color: #29ABE0; +} + +.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(41, 171, 224, 0.5); + box-shadow: 0 0 0 0.2rem rgba(41, 171, 224, 0.5); +} + +.btn-outline-warning { + color: #F47C3C; + background-color: transparent; + background-image: none; + border-color: #F47C3C; +} + +.btn-outline-warning:hover { + color: #fff; + background-color: #F47C3C; + border-color: #F47C3C; +} + +.btn-outline-warning:focus, .btn-outline-warning.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(244, 124, 60, 0.5); + box-shadow: 0 0 0 0.2rem rgba(244, 124, 60, 0.5); +} + +.btn-outline-warning.disabled, .btn-outline-warning:disabled { + color: #F47C3C; + 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: #fff; + background-color: #F47C3C; + border-color: #F47C3C; +} + +.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(244, 124, 60, 0.5); + box-shadow: 0 0 0 0.2rem rgba(244, 124, 60, 0.5); +} + +.btn-outline-danger { + color: #d9534f; + background-color: transparent; + background-image: none; + border-color: #d9534f; +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #d9534f; + border-color: #d9534f; +} + +.btn-outline-danger:focus, .btn-outline-danger.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.5); + box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.5); +} + +.btn-outline-danger.disabled, .btn-outline-danger:disabled { + color: #d9534f; + 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: #d9534f; + border-color: #d9534f; +} + +.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.5); + box-shadow: 0 0 0 0.2rem rgba(217, 83, 79, 0.5); +} + +.btn-outline-light { + color: #F8F5F0; + background-color: transparent; + background-image: none; + border-color: #F8F5F0; +} + +.btn-outline-light:hover { + color: #212529; + background-color: #F8F5F0; + border-color: #F8F5F0; +} + +.btn-outline-light:focus, .btn-outline-light.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 245, 240, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 245, 240, 0.5); +} + +.btn-outline-light.disabled, .btn-outline-light:disabled { + color: #F8F5F0; + 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: #F8F5F0; + border-color: #F8F5F0; +} + +.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(248, 245, 240, 0.5); + box-shadow: 0 0 0 0.2rem rgba(248, 245, 240, 0.5); +} + +.btn-outline-dark { + color: #3E3F3A; + background-color: transparent; + background-image: none; + border-color: #3E3F3A; +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #3E3F3A; + border-color: #3E3F3A; +} + +.btn-outline-dark:focus, .btn-outline-dark.focus { + -webkit-box-shadow: 0 0 0 0.2rem rgba(62, 63, 58, 0.5); + box-shadow: 0 0 0 0.2rem rgba(62, 63, 58, 0.5); +} + +.btn-outline-dark.disabled, .btn-outline-dark:disabled { + color: #3E3F3A; + 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: #3E3F3A; + border-color: #3E3F3A; +} + +.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 { + -webkit-box-shadow: 0 0 0 0.2rem rgba(62, 63, 58, 0.5); + box-shadow: 0 0 0 0.2rem rgba(62, 63, 58, 0.5); +} + +.btn-link { + font-weight: 400; + color: #93C54B; + background-color: transparent; +} + +.btn-link:hover { + color: #6b9430; + text-decoration: underline; + background-color: transparent; + border-color: transparent; +} + +.btn-link:focus, .btn-link.focus { + text-decoration: underline; + border-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} + +.btn-link:disabled, .btn-link.disabled { + color: #8E8C84; + pointer-events: none; +} + +.btn-lg, .btn-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.09375rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.btn-sm, .btn-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.765625rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.btn-block { + display: block; + width: 100%; +} + +.btn-block + .btn-block { + margin-top: 0.5rem; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.fade { + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +@media screen and (prefers-reduced-motion: reduce) { + .fade { + -webkit-transition: none; + transition: none; + } +} + +.fade:not(.show) { + opacity: 0; +} + +.collapse:not(.show) { + display: none; +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +@media screen and (prefers-reduced-motion: reduce) { + .collapsing { + -webkit-transition: none; + transition: none; + } +} + +.dropup, +.dropright, +.dropdown, +.dropleft { + position: relative; +} + +.dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.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: 0.5rem 0; + margin: 0.125rem 0 0; + font-size: 0.875rem; + color: #3E3F3A; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} + +.dropdown-menu-right { + right: 0; + left: auto; +} + +.dropup .dropdown-menu { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 0.125rem; +} + +.dropup .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.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: 0.125rem; +} + +.dropright .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.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: 0.125rem; +} + +.dropleft .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; +} + +.dropleft .dropdown-toggle::after { + display: none; +} + +.dropleft .dropdown-toggle::before { + display: inline-block; + width: 0; + height: 0; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} + +.dropleft .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropleft .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-menu[x-placement^="top"], .dropdown-menu[x-placement^="right"], .dropdown-menu[x-placement^="bottom"], .dropdown-menu[x-placement^="left"] { + right: auto; + bottom: auto; +} + +.dropdown-divider { + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid #F8F5F0; +} + +.dropdown-item { + display: block; + width: 100%; + padding: 0.25rem 1.5rem; + clear: both; + font-weight: 400; + color: #8E8C84; + text-align: inherit; + white-space: nowrap; + background-color: transparent; + border: 0; +} + +.dropdown-item:hover, .dropdown-item:focus { + color: #8E8C84; + text-decoration: none; + background-color: #F8F5F0; +} + +.dropdown-item.active, .dropdown-item:active { + color: #8E8C84; + text-decoration: none; + background-color: #F8F5F0; +} + +.dropdown-item.disabled, .dropdown-item:disabled { + color: #8E8C84; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: 0.5rem 1.5rem; + margin-bottom: 0; + font-size: 0.765625rem; + color: #8E8C84; + white-space: nowrap; +} + +.dropdown-item-text { + display: block; + padding: 0.25rem 1.5rem; + color: #8E8C84; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + vertical-align: middle; +} + +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + -webkit-box-flex: 0; + -ms-flex: 0 1 auto; + flex: 0 1 auto; +} + +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover { + z-index: 1; +} + +.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 1; +} + +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group, +.btn-group-vertical .btn + .btn, +.btn-group-vertical .btn + .btn-group, +.btn-group-vertical .btn-group + .btn, +.btn-group-vertical .btn-group + .btn-group { + margin-left: -1px; +} + +.btn-toolbar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.btn-toolbar .input-group { + width: auto; +} + +.btn-group > .btn:first-child { + margin-left: 0; +} + +.btn-group > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.dropdown-toggle-split { + padding-right: 0.5625rem; + padding-left: 0.5625rem; +} + +.dropdown-toggle-split::after, +.dropup .dropdown-toggle-split::after, +.dropright .dropdown-toggle-split::after { + margin-left: 0; +} + +.dropleft .dropdown-toggle-split::before { + margin-right: 0; +} + +.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} + +.btn-group-vertical { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} + +.btn-group-vertical .btn, +.btn-group-vertical .btn-group { + width: 100%; +} + +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group-vertical > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) > .btn { + 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="radio"], +.btn-group-toggle > .btn input[type="checkbox"], +.btn-group-toggle > .btn-group > .btn input[type="radio"], +.btn-group-toggle > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} + +.input-group { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: stretch; + -ms-flex-align: stretch; + align-items: stretch; + width: 100%; +} + +.input-group > .form-control, +.input-group > .custom-select, +.input-group > .custom-file { + position: relative; + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + width: 1%; + margin-bottom: 0; +} + +.input-group > .form-control:focus, +.input-group > .custom-select:focus, +.input-group > .custom-file:focus { + z-index: 3; +} + +.input-group > .form-control + .form-control, +.input-group > .form-control + .custom-select, +.input-group > .form-control + .custom-file, +.input-group > .custom-select + .form-control, +.input-group > .custom-select + .custom-select, +.input-group > .custom-select + .custom-file, +.input-group > .custom-file + .form-control, +.input-group > .custom-file + .custom-select, +.input-group > .custom-file + .custom-file { + margin-left: -1px; +} + +.input-group > .form-control:not(:last-child), +.input-group > .custom-select:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .form-control:not(:first-child), +.input-group > .custom-select:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group > .custom-file { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.input-group > .custom-file:not(:last-child) .custom-file-label, +.input-group > .custom-file:not(:last-child) .custom-file-label::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-prepend, +.input-group-append { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +.input-group-prepend .btn, +.input-group-append .btn { + position: relative; + z-index: 2; +} + +.input-group-prepend .btn + .btn, +.input-group-prepend .btn + .input-group-text, +.input-group-prepend .input-group-text + .input-group-text, +.input-group-prepend .input-group-text + .btn, +.input-group-append .btn + .btn, +.input-group-append .btn + .input-group-text, +.input-group-append .input-group-text + .input-group-text, +.input-group-append .input-group-text + .btn { + margin-left: -1px; +} + +.input-group-prepend { + margin-right: -1px; +} + +.input-group-append { + margin-left: -1px; +} + +.input-group-text { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + padding: 0.375rem 0.75rem; + margin-bottom: 0; + font-size: 0.875rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + text-align: center; + white-space: nowrap; + background-color: #F8F5F0; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.input-group-text input[type="radio"], +.input-group-text input[type="checkbox"] { + margin-top: 0; +} + +.input-group > .input-group-prepend > .btn, +.input-group > .input-group-prepend > .input-group-text, +.input-group > .input-group-append:not(:last-child) > .btn, +.input-group > .input-group-append:not(:last-child) > .input-group-text, +.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) { + 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:not(:first-child) > .btn, +.input-group > .input-group-prepend:not(:first-child) > .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) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.custom-control { + position: relative; + display: block; + min-height: 1.5rem; + padding-left: 1.5rem; +} + +.custom-control-inline { + display: -webkit-inline-box; + display: -ms-inline-flexbox; + display: inline-flex; + margin-right: 1rem; +} + +.custom-control-input { + position: absolute; + z-index: -1; + opacity: 0; +} + +.custom-control-input:checked ~ .custom-control-label::before { + color: #fff; + background-color: #325D88; +} + +.custom-control-input:focus ~ .custom-control-label::before { + -webkit-box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(50, 93, 136, 0.25); + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(50, 93, 136, 0.25); +} + +.custom-control-input:active ~ .custom-control-label::before { + color: #fff; + background-color: #95b6d8; +} + +.custom-control-input:disabled ~ .custom-control-label { + color: #8E8C84; +} + +.custom-control-input:disabled ~ .custom-control-label::before { + background-color: #F8F5F0; +} + +.custom-control-label { + position: relative; + margin-bottom: 0; +} + +.custom-control-label::before { + position: absolute; + top: 0.25rem; + left: -1.5rem; + display: block; + width: 1rem; + height: 1rem; + pointer-events: none; + content: ""; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: #DFD7CA; +} + +.custom-control-label::after { + position: absolute; + top: 0.25rem; + left: -1.5rem; + display: block; + width: 1rem; + height: 1rem; + content: ""; + background-repeat: no-repeat; + background-position: center center; + background-size: 50% 50%; +} + +.custom-checkbox .custom-control-label::before { + border-radius: 0.25rem; +} + +.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before { + background-color: #325D88; +} + +.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); +} + +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { + background-color: #325D88; +} + +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); +} + +.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(50, 93, 136, 0.5); +} + +.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before { + background-color: rgba(50, 93, 136, 0.5); +} + +.custom-radio .custom-control-label::before { + border-radius: 50%; +} + +.custom-radio .custom-control-input:checked ~ .custom-control-label::before { + background-color: #325D88; +} + +.custom-radio .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); +} + +.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(50, 93, 136, 0.5); +} + +.custom-select { + display: inline-block; + width: 100%; + height: calc(2.0625rem + 2px); + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%233E3F3A' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 8px 10px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-select:focus { + border-color: #6f9dca; + outline: 0; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 5px rgba(111, 157, 202, 0.5); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 5px rgba(111, 157, 202, 0.5); +} + +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.custom-select[multiple], .custom-select[size]:not([size="1"]) { + height: auto; + padding-right: 0.75rem; + background-image: none; +} + +.custom-select:disabled { + color: #8E8C84; + background-color: #F8F5F0; +} + +.custom-select::-ms-expand { + opacity: 0; +} + +.custom-select-sm { + height: calc(1.6484375rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 75%; +} + +.custom-select-lg { + height: calc(2.640625rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 125%; +} + +.custom-file { + position: relative; + display: inline-block; + width: 100%; + height: calc(2.0625rem + 2px); + margin-bottom: 0; +} + +.custom-file-input { + position: relative; + z-index: 2; + width: 100%; + height: calc(2.0625rem + 2px); + margin: 0; + opacity: 0; +} + +.custom-file-input:focus ~ .custom-file-label { + border-color: #6f9dca; + -webkit-box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.25); + box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.25); +} + +.custom-file-input:focus ~ .custom-file-label::after { + border-color: #6f9dca; +} + +.custom-file-input:lang(en) ~ .custom-file-label::after { + content: "Browse"; +} + +.custom-file-label { + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 1; + height: calc(2.0625rem + 2px); + padding: 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.custom-file-label::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + z-index: 3; + display: block; + height: 2.0625rem; + padding: 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + content: "Browse"; + background-color: #F8F5F0; + border-left: 1px solid #ced4da; + border-radius: 0 0.25rem 0.25rem 0; +} + +.custom-range { + width: 100%; + padding-left: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-range:focus { + outline: none; +} + +.custom-range::-moz-focus-outer { + border: 0; +} + +.custom-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #325D88; + border: 0; + border-radius: 1rem; + -webkit-appearance: none; + appearance: none; +} + +.custom-range::-webkit-slider-thumb:focus { + outline: none; + -webkit-box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(50, 93, 136, 0.25); + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(50, 93, 136, 0.25); +} + +.custom-range::-webkit-slider-thumb:active { + background-color: #95b6d8; +} + +.custom-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #DFD7CA; + border-color: transparent; + border-radius: 1rem; +} + +.custom-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #325D88; + border: 0; + border-radius: 1rem; + -moz-appearance: none; + appearance: none; +} + +.custom-range::-moz-range-thumb:focus { + outline: none; + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(50, 93, 136, 0.25); +} + +.custom-range::-moz-range-thumb:active { + background-color: #95b6d8; +} + +.custom-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #DFD7CA; + border-color: transparent; + border-radius: 1rem; +} + +.custom-range::-ms-thumb { + width: 1rem; + height: 1rem; + background-color: #325D88; + border: 0; + border-radius: 1rem; + appearance: none; +} + +.custom-range::-ms-thumb:focus { + outline: none; + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(50, 93, 136, 0.25); +} + +.custom-range::-ms-thumb:active { + background-color: #95b6d8; +} + +.custom-range::-ms-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: transparent; + border-color: transparent; + border-width: 0.5rem; +} + +.custom-range::-ms-fill-lower { + background-color: #DFD7CA; + border-radius: 1rem; +} + +.custom-range::-ms-fill-upper { + margin-right: 15px; + background-color: #DFD7CA; + border-radius: 1rem; +} + +.nav { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: 0.5rem 0.9rem; +} + +.nav-link:hover, .nav-link:focus { + text-decoration: none; +} + +.nav-link.disabled { + color: #DFD7CA; +} + +.nav-tabs { + border-bottom: 1px solid #DFD7CA; +} + +.nav-tabs .nav-item { + margin-bottom: -1px; +} + +.nav-tabs .nav-link { + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { + border-color: #DFD7CA; +} + +.nav-tabs .nav-link.disabled { + color: #DFD7CA; + background-color: transparent; + border-color: transparent; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; + border-color: #DFD7CA #DFD7CA #fff; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-pills .nav-link { + border-radius: 0.25rem; +} + +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #8E8C84; + background-color: #F8F5F0; +} + +.nav-fill .nav-item { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + text-align: center; +} + +.nav-justified .nav-item { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + text-align: center; +} + +.tab-content > .tab-pane { + display: none; +} + +.tab-content > .active { + display: block; +} + +.navbar { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 0.5rem 1rem; +} + +.navbar > .container, +.navbar > .container-fluid { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +.navbar-brand { + display: inline-block; + padding-top: 0.3359375rem; + padding-bottom: 0.3359375rem; + margin-right: 1rem; + font-size: 1.09375rem; + line-height: inherit; + white-space: nowrap; +} + +.navbar-brand:hover, .navbar-brand:focus { + text-decoration: none; +} + +.navbar-nav { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0; +} + +.navbar-nav .dropdown-menu { + position: static; + float: none; +} + +.navbar-text { + display: inline-block; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.navbar-collapse { + -ms-flex-preferred-size: 100%; + flex-basis: 100%; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.09375rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.navbar-toggler:hover, .navbar-toggler:focus { + text-decoration: none; +} + +.navbar-toggler:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + content: ""; + background: no-repeat center center; + background-size: 100% 100%; +} + +@media (max-width: 575.98px) { + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 576px) { + .navbar-expand-sm { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-sm .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-sm .navbar-collapse { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-sm .navbar-toggler { + display: none; + } +} + +@media (max-width: 767.98px) { + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 768px) { + .navbar-expand-md { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-md .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-md .navbar-collapse { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-md .navbar-toggler { + display: none; + } +} + +@media (max-width: 991.98px) { + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 992px) { + .navbar-expand-lg { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-lg .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-lg .navbar-collapse { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-lg .navbar-toggler { + display: none; + } +} + +@media (max-width: 1199.98px) { + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-xl .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-xl .navbar-collapse { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-xl .navbar-toggler { + display: none; + } +} + +.navbar-expand { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.navbar-expand > .container, +.navbar-expand > .container-fluid { + padding-right: 0; + padding-left: 0; +} + +.navbar-expand .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} + +.navbar-expand .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; +} + +.navbar-expand > .container, +.navbar-expand > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; +} + +.navbar-expand .navbar-collapse { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; +} + +.navbar-expand .navbar-toggler { + display: none; +} + +.navbar-light .navbar-brand { + color: #000; +} + +.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { + color: #000; +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { + color: #000; +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} + +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .active > .nav-link, +.navbar-light .navbar-nav .nav-link.show, +.navbar-light .navbar-nav .nav-link.active { + color: #000; +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.5); + border-color: rgba(0, 0, 0, 0.1); +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-text a { + color: #000; +} + +.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus { + color: #000; +} + +.navbar-dark .navbar-brand { + color: #fff; +} + +.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} + +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .active > .nav-link, +.navbar-dark .navbar-nav .nav-link.show, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.5); + border-color: rgba(255, 255, 255, 0.1); +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-text a { + color: #fff; +} + +.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus { + color: #fff; +} + +.card { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(223, 215, 202, 0.75); + border-radius: 0.25rem; +} + +.card > hr { + margin-right: 0; + margin-left: 0; +} + +.card > .list-group:first-child .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.card > .list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.card-body { + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1.25rem; +} + +.card-title { + margin-bottom: 0.75rem; +} + +.card-subtitle { + margin-top: -0.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: 0.75rem 1.25rem; + margin-bottom: 0; + background-color: rgba(248, 245, 240, 0.25); + border-bottom: 1px solid rgba(223, 215, 202, 0.75); +} + +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} + +.card-header + .list-group .list-group-item:first-child { + border-top: 0; +} + +.card-footer { + padding: 0.75rem 1.25rem; + background-color: rgba(248, 245, 240, 0.25); + border-top: 1px solid rgba(223, 215, 202, 0.75); +} + +.card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); +} + +.card-header-tabs { + margin-right: -0.625rem; + margin-bottom: -0.75rem; + margin-left: -0.625rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.625rem; + margin-left: -0.625rem; +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1.25rem; +} + +.card-img { + width: 100%; + border-radius: calc(0.25rem - 1px); +} + +.card-img-top { + width: 100%; + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card-img-bottom { + width: 100%; + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card-deck { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} + +.card-deck .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-deck { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + margin-right: -15px; + margin-left: -15px; + } + .card-deck .card { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + margin-right: 15px; + margin-bottom: 0; + margin-left: 15px; + } +} + +.card-group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} + +.card-group > .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-group { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + } + .card-group > .card { + -webkit-box-flex: 1; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + margin-bottom: 0; + } + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + .card-group > .card:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .card-group > .card:first-child .card-img-top, + .card-group > .card:first-child .card-header { + border-top-right-radius: 0; + } + .card-group > .card:first-child .card-img-bottom, + .card-group > .card:first-child .card-footer { + border-bottom-right-radius: 0; + } + .card-group > .card:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .card-group > .card:last-child .card-img-top, + .card-group > .card:last-child .card-header { + border-top-left-radius: 0; + } + .card-group > .card:last-child .card-img-bottom, + .card-group > .card:last-child .card-footer { + border-bottom-left-radius: 0; + } + .card-group > .card:only-child { + border-radius: 0.25rem; + } + .card-group > .card:only-child .card-img-top, + .card-group > .card:only-child .card-header { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + } + .card-group > .card:only-child .card-img-bottom, + .card-group > .card:only-child .card-footer { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + } + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) { + border-radius: 0; + } + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer { + border-radius: 0; + } +} + +.card-columns .card { + margin-bottom: 0.75rem; +} + +@media (min-width: 576px) { + .card-columns { + -webkit-column-count: 3; + column-count: 3; + -webkit-column-gap: 1.25rem; + column-gap: 1.25rem; + orphans: 1; + widows: 1; + } + .card-columns .card { + display: inline-block; + width: 100%; + } +} + +.accordion .card:not(:first-of-type):not(:last-of-type) { + border-bottom: 0; + border-radius: 0; +} + +.accordion .card:not(:first-of-type) .card-header:first-child { + border-radius: 0; +} + +.accordion .card:first-of-type { + border-bottom: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.accordion .card:last-of-type { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.breadcrumb { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + padding: 0.75rem 1rem; + margin-bottom: 1rem; + list-style: none; + background-color: #F8F5F0; + border-radius: 0.25rem; +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: 0.5rem; +} + +.breadcrumb-item + .breadcrumb-item::before { + display: inline-block; + padding-right: 0.5rem; + color: #8E8C84; + content: "/"; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: underline; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: none; +} + +.breadcrumb-item.active { + color: #8E8C84; +} + +.pagination { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + padding-left: 0; + list-style: none; + border-radius: 0.25rem; +} + +.page-link { + position: relative; + display: block; + padding: 0.5rem 0.75rem; + margin-left: -1px; + line-height: 1.25; + color: #8E8C84; + background-color: #F8F5F0; + border: 1px solid #DFD7CA; +} + +.page-link:hover { + z-index: 2; + color: #8E8C84; + text-decoration: none; + background-color: #F8F5F0; + border-color: #DFD7CA; +} + +.page-link:focus { + z-index: 2; + outline: 0; + -webkit-box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.25); + box-shadow: 0 0 0 0.2rem rgba(50, 93, 136, 0.25); +} + +.page-link:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.page-item:first-child .page-link { + margin-left: 0; + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.page-item.active .page-link { + z-index: 1; + color: #8E8C84; + background-color: #DFD7CA; + border-color: #DFD7CA; +} + +.page-item.disabled .page-link { + color: #DFD7CA; + pointer-events: none; + cursor: auto; + background-color: #F8F5F0; + border-color: #DFD7CA; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.09375rem; + line-height: 1.5; +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.765625rem; + line-height: 1.5; +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +.badge { + display: inline-block; + padding: 0.25em 0.4em; + font-size: 75%; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; +} + +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.badge-pill { + padding-right: 0.6em; + padding-left: 0.6em; + border-radius: 10rem; +} + +.badge-primary { + color: #fff; + background-color: #325D88; +} + +.badge-primary[href]:hover, .badge-primary[href]:focus { + color: #fff; + text-decoration: none; + background-color: #244463; +} + +.badge-secondary { + color: #fff; + background-color: #8E8C84; +} + +.badge-secondary[href]:hover, .badge-secondary[href]:focus { + color: #fff; + text-decoration: none; + background-color: #74726b; +} + +.badge-success { + color: #fff; + background-color: #93C54B; +} + +.badge-success[href]:hover, .badge-success[href]:focus { + color: #fff; + text-decoration: none; + background-color: #79a736; +} + +.badge-info { + color: #fff; + background-color: #29ABE0; +} + +.badge-info[href]:hover, .badge-info[href]:focus { + color: #fff; + text-decoration: none; + background-color: #1b8dbb; +} + +.badge-warning { + color: #fff; + background-color: #F47C3C; +} + +.badge-warning[href]:hover, .badge-warning[href]:focus { + color: #fff; + text-decoration: none; + background-color: #ef5c0e; +} + +.badge-danger { + color: #fff; + background-color: #d9534f; +} + +.badge-danger[href]:hover, .badge-danger[href]:focus { + color: #fff; + text-decoration: none; + background-color: #c9302c; +} + +.badge-light { + color: #212529; + background-color: #F8F5F0; +} + +.badge-light[href]:hover, .badge-light[href]:focus { + color: #212529; + text-decoration: none; + background-color: #e8decd; +} + +.badge-dark { + color: #fff; + background-color: #3E3F3A; +} + +.badge-dark[href]:hover, .badge-dark[href]:focus { + color: #fff; + text-decoration: none; + background-color: #242422; +} + +.jumbotron { + padding: 2rem 1rem; + margin-bottom: 2rem; + background-color: #F8F5F0; + border-radius: 0.3rem; +} + +@media (min-width: 576px) { + .jumbotron { + padding: 4rem 2rem; + } +} + +.jumbotron-fluid { + padding-right: 0; + padding-left: 0; + border-radius: 0; +} + +.alert { + position: relative; + padding: 0.75rem 1.25rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; +} + +.alert-dismissible { + padding-right: 3.8125rem; +} + +.alert-dismissible .close { + position: absolute; + top: 0; + right: 0; + padding: 0.75rem 1.25rem; + color: inherit; +} + +.alert-primary { + color: #1a3047; + background-color: #d6dfe7; + border-color: #c6d2de; +} + +.alert-primary hr { + border-top-color: #b6c5d5; +} + +.alert-primary .alert-link { + color: #0c1722; +} + +.alert-secondary { + color: #4a4945; + background-color: #e8e8e6; + border-color: #dfdfdd; +} + +.alert-secondary hr { + border-top-color: #d3d3d0; +} + +.alert-secondary .alert-link { + color: #302f2c; +} + +.alert-success { + color: #4c6627; + background-color: #e9f3db; + border-color: #e1efcd; +} + +.alert-success hr { + border-top-color: #d5e9ba; +} + +.alert-success .alert-link { + color: #314119; +} + +.alert-info { + color: #155974; + background-color: #d4eef9; + border-color: #c3e7f6; +} + +.alert-info hr { + border-top-color: #addef3; +} + +.alert-info .alert-link { + color: #0d3849; +} + +.alert-warning { + color: #7f401f; + background-color: #fde5d8; + border-color: #fcdac8; +} + +.alert-warning hr { + border-top-color: #fbcab0; +} + +.alert-warning .alert-link { + color: #562b15; +} + +.alert-danger { + color: #712b29; + background-color: #f7dddc; + border-color: #f4cfce; +} + +.alert-danger hr { + border-top-color: #efbbb9; +} + +.alert-danger .alert-link { + color: #4c1d1b; +} + +.alert-light { + color: #817f7d; + background-color: #fefdfc; + border-color: #fdfcfb; +} + +.alert-light hr { + border-top-color: #f5efea; +} + +.alert-light .alert-link { + color: #676664; +} + +.alert-dark { + color: #20211e; + background-color: #d8d9d8; + border-color: #c9c9c8; +} + +.alert-dark hr { + border-top-color: #bcbcbb; +} + +.alert-dark .alert-link { + color: #060606; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 1rem 0; + } + to { + background-position: 0 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 1rem 0; + } + to { + background-position: 0 0; + } +} + +.progress { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + height: 1rem; + overflow: hidden; + font-size: 0.65625rem; + background-color: #DFD7CA; + border-radius: 10px; +} + +.progress-bar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + color: #325D88; + text-align: center; + white-space: nowrap; + background-color: #325D88; + -webkit-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +@media screen and (prefers-reduced-motion: reduce) { + .progress-bar { + -webkit-transition: none; + transition: none; + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 1rem 1rem; +} + +.progress-bar-animated { + -webkit-animation: progress-bar-stripes 1s linear infinite; + animation: progress-bar-stripes 1s linear infinite; +} + +.media { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; +} + +.media-body { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; +} + +.list-group { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; +} + +.list-group-item-action { + width: 100%; + color: #3E3F3A; + text-align: inherit; +} + +.list-group-item-action:hover, .list-group-item-action:focus { + color: #3E3F3A; + text-decoration: none; + background-color: #F8F5F0; +} + +.list-group-item-action:active { + color: #3E3F3A; + background-color: #DFD7CA; +} + +.list-group-item { + position: relative; + display: block; + padding: 0.75rem 1.25rem; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #DFD7CA; +} + +.list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.list-group-item:hover, .list-group-item:focus { + z-index: 1; + text-decoration: none; +} + +.list-group-item.disabled, .list-group-item:disabled { + color: #98978B; + background-color: #fff; +} + +.list-group-item.active { + z-index: 2; + color: #3E3F3A; + background-color: #F8F5F0; + border-color: #DFD7CA; +} + +.list-group-flush .list-group-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} + +.list-group-flush:first-child .list-group-item:first-child { + border-top: 0; +} + +.list-group-flush:last-child .list-group-item:last-child { + border-bottom: 0; +} + +.list-group-item-primary { + color: #1a3047; + background-color: #c6d2de; +} + +.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { + color: #1a3047; + background-color: #b6c5d5; +} + +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #1a3047; + border-color: #1a3047; +} + +.list-group-item-secondary { + color: #4a4945; + background-color: #dfdfdd; +} + +.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { + color: #4a4945; + background-color: #d3d3d0; +} + +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #4a4945; + border-color: #4a4945; +} + +.list-group-item-success { + color: #4c6627; + background-color: #e1efcd; +} + +.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { + color: #4c6627; + background-color: #d5e9ba; +} + +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #4c6627; + border-color: #4c6627; +} + +.list-group-item-info { + color: #155974; + background-color: #c3e7f6; +} + +.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { + color: #155974; + background-color: #addef3; +} + +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #155974; + border-color: #155974; +} + +.list-group-item-warning { + color: #7f401f; + background-color: #fcdac8; +} + +.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { + color: #7f401f; + background-color: #fbcab0; +} + +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #7f401f; + border-color: #7f401f; +} + +.list-group-item-danger { + color: #712b29; + background-color: #f4cfce; +} + +.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { + color: #712b29; + background-color: #efbbb9; +} + +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #712b29; + border-color: #712b29; +} + +.list-group-item-light { + color: #817f7d; + background-color: #fdfcfb; +} + +.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { + color: #817f7d; + background-color: #f5efea; +} + +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #817f7d; + border-color: #817f7d; +} + +.list-group-item-dark { + color: #20211e; + background-color: #c9c9c8; +} + +.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { + color: #20211e; + background-color: #bcbcbb; +} + +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #20211e; + border-color: #20211e; +} + +.close { + float: right; + font-size: 1.3125rem; + font-weight: 700; + line-height: 1; + color: #000; + text-shadow: none; + opacity: .5; +} + +.close:hover, .close:focus { + color: #000; + text-decoration: none; + opacity: .75; +} + +.close:not(:disabled):not(.disabled) { + cursor: pointer; +} + +button.close { + padding: 0; + background-color: transparent; + border: 0; + -webkit-appearance: none; +} + +.modal-open { + overflow: hidden; +} + +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + outline: 0; +} + +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 0.5rem; + pointer-events: none; +} + +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform 0.3s ease-out; + transition: -webkit-transform 0.3s ease-out; + transition: transform 0.3s ease-out; + transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; + -webkit-transform: translate(0, -25%); + transform: translate(0, -25%); +} + +@media screen and (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + -webkit-transition: none; + transition: none; + } +} + +.modal.show .modal-dialog { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); +} + +.modal-dialog-centered { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + min-height: calc(100% - (0.5rem * 2)); +} + +.modal-content { + position: relative; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + width: 100%; + pointer-events: auto; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #DFD7CA; + border-radius: 0.3rem; + outline: 0; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop.show { + opacity: 0.5; +} + +.modal-header { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 1rem; + border-bottom: 1px solid #DFD7CA; + border-top-left-radius: 0.3rem; + border-top-right-radius: 0.3rem; +} + +.modal-header .close { + padding: 1rem; + margin: -1rem -1rem -1rem auto; +} + +.modal-title { + margin-bottom: 0; + line-height: 1.5; +} + +.modal-body { + position: relative; + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1rem; +} + +.modal-footer { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + padding: 1rem; + border-top: 1px solid #DFD7CA; +} + +.modal-footer > :not(:first-child) { + margin-left: .25rem; +} + +.modal-footer > :not(:last-child) { + margin-right: .25rem; +} + +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 1.75rem auto; + } + .modal-dialog-centered { + min-height: calc(100% - (1.75rem * 2)); + } + .modal-sm { + max-width: 300px; + } +} + +@media (min-width: 992px) { + .modal-lg { + max-width: 800px; + } +} + +.tooltip { + position: absolute; + z-index: 1070; + display: block; + margin: 0; + font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.765625rem; + word-wrap: break-word; + opacity: 0; +} + +.tooltip.show { + opacity: 0.9; +} + +.tooltip .arrow { + position: absolute; + display: block; + width: 0.8rem; + height: 0.4rem; +} + +.tooltip .arrow::before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] { + padding: 0.4rem 0; +} + +.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow { + bottom: 0; +} + +.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before { + top: 0; + border-width: 0.4rem 0.4rem 0; + border-top-color: #000; +} + +.bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] { + padding: 0 0.4rem; +} + +.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow { + left: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before { + right: 0; + border-width: 0.4rem 0.4rem 0.4rem 0; + border-right-color: #000; +} + +.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] { + padding: 0.4rem 0; +} + +.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow { + top: 0; +} + +.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before { + bottom: 0; + border-width: 0 0.4rem 0.4rem; + border-bottom-color: #000; +} + +.bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] { + padding: 0 0.4rem; +} + +.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow { + right: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before { + left: 0; + border-width: 0.4rem 0 0.4rem 0.4rem; + border-left-color: #000; +} + +.tooltip-inner { + max-width: 200px; + padding: 0.25rem 0.5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 0.25rem; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: block; + max-width: 276px; + font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.765625rem; + word-wrap: break-word; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; +} + +.popover .arrow { + position: absolute; + display: block; + width: 1rem; + height: 0.5rem; + margin: 0 0.3rem; +} + +.popover .arrow::before, .popover .arrow::after { + position: absolute; + display: block; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-popover-top, .bs-popover-auto[x-placement^="top"] { + margin-bottom: 0.5rem; +} + +.bs-popover-top .arrow, .bs-popover-auto[x-placement^="top"] .arrow { + bottom: calc((0.5rem + 1px) * -1); +} + +.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before, +.bs-popover-top .arrow::after, .bs-popover-auto[x-placement^="top"] .arrow::after { + border-width: 0.5rem 0.5rem 0; +} + +.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before { + bottom: 0; + border-top-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-top .arrow::after, .bs-popover-auto[x-placement^="top"] .arrow::after { + bottom: 1px; + border-top-color: #fff; +} + +.bs-popover-right, .bs-popover-auto[x-placement^="right"] { + margin-left: 0.5rem; +} + +.bs-popover-right .arrow, .bs-popover-auto[x-placement^="right"] .arrow { + left: calc((0.5rem + 1px) * -1); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} + +.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before, +.bs-popover-right .arrow::after, .bs-popover-auto[x-placement^="right"] .arrow::after { + border-width: 0.5rem 0.5rem 0.5rem 0; +} + +.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before { + left: 0; + border-right-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-right .arrow::after, .bs-popover-auto[x-placement^="right"] .arrow::after { + left: 1px; + border-right-color: #fff; +} + +.bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] { + margin-top: 0.5rem; +} + +.bs-popover-bottom .arrow, .bs-popover-auto[x-placement^="bottom"] .arrow { + top: calc((0.5rem + 1px) * -1); +} + +.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before, +.bs-popover-bottom .arrow::after, .bs-popover-auto[x-placement^="bottom"] .arrow::after { + border-width: 0 0.5rem 0.5rem 0.5rem; +} + +.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before { + top: 0; + border-bottom-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-bottom .arrow::after, .bs-popover-auto[x-placement^="bottom"] .arrow::after { + top: 1px; + border-bottom-color: #fff; +} + +.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 1rem; + margin-left: -0.5rem; + content: ""; + border-bottom: 1px solid #F8F5F0; +} + +.bs-popover-left, .bs-popover-auto[x-placement^="left"] { + margin-right: 0.5rem; +} + +.bs-popover-left .arrow, .bs-popover-auto[x-placement^="left"] .arrow { + right: calc((0.5rem + 1px) * -1); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} + +.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before, +.bs-popover-left .arrow::after, .bs-popover-auto[x-placement^="left"] .arrow::after { + border-width: 0.5rem 0 0.5rem 0.5rem; +} + +.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before { + right: 0; + border-left-color: rgba(0, 0, 0, 0.25); +} + +.bs-popover-left .arrow::after, .bs-popover-auto[x-placement^="left"] .arrow::after { + right: 1px; + border-left-color: #fff; +} + +.popover-header { + padding: 0.5rem 0.75rem; + margin-bottom: 0; + font-size: 0.875rem; + color: inherit; + background-color: #F8F5F0; + border-bottom: 1px solid #f0e9df; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} + +.popover-header:empty { + display: none; +} + +.popover-body { + padding: 0.5rem 0.75rem; + color: #3E3F3A; +} + +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-item { + position: relative; + display: none; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-transition: -webkit-transform 0.6s ease; + transition: -webkit-transform 0.6s ease; + transition: transform 0.6s ease; + transition: transform 0.6s ease, -webkit-transform 0.6s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; +} + +@media screen and (prefers-reduced-motion: reduce) { + .carousel-item { + -webkit-transition: none; + transition: none; + } +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + +.carousel-item-next, +.carousel-item-prev { + position: absolute; + top: 0; +} + +.carousel-item-next.carousel-item-left, +.carousel-item-prev.carousel-item-right { + -webkit-transform: translateX(0); + transform: translateX(0); +} + +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-next.carousel-item-left, + .carousel-item-prev.carousel-item-right { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.carousel-item-next, +.active.carousel-item-right { + -webkit-transform: translateX(100%); + transform: translateX(100%); +} + +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-next, + .active.carousel-item-right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.carousel-item-prev, +.active.carousel-item-left { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); +} + +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-prev, + .active.carousel-item-left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.carousel-fade .carousel-item { + opacity: 0; + -webkit-transition-duration: .6s; + transition-duration: .6s; + -webkit-transition-property: opacity; + transition-property: opacity; +} + +.carousel-fade .carousel-item.active, +.carousel-fade .carousel-item-next.carousel-item-left, +.carousel-fade .carousel-item-prev.carousel-item-right { + opacity: 1; +} + +.carousel-fade .active.carousel-item-left, +.carousel-fade .active.carousel-item-right { + opacity: 0; +} + +.carousel-fade .carousel-item-next, +.carousel-fade .carousel-item-prev, +.carousel-fade .carousel-item.active, +.carousel-fade .active.carousel-item-left, +.carousel-fade .active.carousel-item-prev { + -webkit-transform: translateX(0); + transform: translateX(0); +} + +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-fade .carousel-item-next, + .carousel-fade .carousel-item-prev, + .carousel-fade .carousel-item.active, + .carousel-fade .active.carousel-item-left, + .carousel-fade .active.carousel-item-prev { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + width: 15%; + color: #fff; + text-align: center; + opacity: 0.5; +} + +.carousel-control-prev:hover, .carousel-control-prev:focus, +.carousel-control-next:hover, +.carousel-control-next:focus { + color: #fff; + text-decoration: none; + outline: 0; + opacity: .9; +} + +.carousel-control-prev { + left: 0; +} + +.carousel-control-next { + right: 0; +} + +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: 20px; + height: 20px; + background: transparent no-repeat center center; + background-size: 100% 100%; +} + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 10px; + left: 0; + z-index: 15; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + padding-left: 0; + margin-right: 15%; + margin-left: 15%; + list-style: none; +} + +.carousel-indicators li { + position: relative; + -webkit-box-flex: 0; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + width: 30px; + height: 3px; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: rgba(255, 255, 255, 0.5); +} + +.carousel-indicators li::before { + position: absolute; + top: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: ""; +} + +.carousel-indicators li::after { + position: absolute; + bottom: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: ""; +} + +.carousel-indicators .active { + background-color: #fff; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; +} + +.align-baseline { + vertical-align: baseline !important; +} + +.align-top { + vertical-align: top !important; +} + +.align-middle { + vertical-align: middle !important; +} + +.align-bottom { + vertical-align: bottom !important; +} + +.align-text-bottom { + vertical-align: text-bottom !important; +} + +.align-text-top { + vertical-align: text-top !important; +} + +.bg-primary { + background-color: #325D88 !important; +} + +a.bg-primary:hover, a.bg-primary:focus, +button.bg-primary:hover, +button.bg-primary:focus { + background-color: #244463 !important; +} + +.bg-secondary { + background-color: #8E8C84 !important; +} + +a.bg-secondary:hover, a.bg-secondary:focus, +button.bg-secondary:hover, +button.bg-secondary:focus { + background-color: #74726b !important; +} + +.bg-success { + background-color: #93C54B !important; +} + +a.bg-success:hover, a.bg-success:focus, +button.bg-success:hover, +button.bg-success:focus { + background-color: #79a736 !important; +} + +.bg-info { + background-color: #29ABE0 !important; +} + +a.bg-info:hover, a.bg-info:focus, +button.bg-info:hover, +button.bg-info:focus { + background-color: #1b8dbb !important; +} + +.bg-warning { + background-color: #F47C3C !important; +} + +a.bg-warning:hover, a.bg-warning:focus, +button.bg-warning:hover, +button.bg-warning:focus { + background-color: #ef5c0e !important; +} + +.bg-danger { + background-color: #d9534f !important; +} + +a.bg-danger:hover, a.bg-danger:focus, +button.bg-danger:hover, +button.bg-danger:focus { + background-color: #c9302c !important; +} + +.bg-light { + background-color: #F8F5F0 !important; +} + +a.bg-light:hover, a.bg-light:focus, +button.bg-light:hover, +button.bg-light:focus { + background-color: #e8decd !important; +} + +.bg-dark { + background-color: #3E3F3A !important; +} + +a.bg-dark:hover, a.bg-dark:focus, +button.bg-dark:hover, +button.bg-dark:focus { + background-color: #242422 !important; +} + +.bg-white { + background-color: #fff !important; +} + +.bg-transparent { + background-color: transparent !important; +} + +.border { + border: 1px solid #DFD7CA !important; +} + +.border-top { + border-top: 1px solid #DFD7CA !important; +} + +.border-right { + border-right: 1px solid #DFD7CA !important; +} + +.border-bottom { + border-bottom: 1px solid #DFD7CA !important; +} + +.border-left { + border-left: 1px solid #DFD7CA !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: #325D88 !important; +} + +.border-secondary { + border-color: #8E8C84 !important; +} + +.border-success { + border-color: #93C54B !important; +} + +.border-info { + border-color: #29ABE0 !important; +} + +.border-warning { + border-color: #F47C3C !important; +} + +.border-danger { + border-color: #d9534f !important; +} + +.border-light { + border-color: #F8F5F0 !important; +} + +.border-dark { + border-color: #3E3F3A !important; +} + +.border-white { + border-color: #fff !important; +} + +.rounded { + border-radius: 0.25rem !important; +} + +.rounded-top { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} + +.rounded-right { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; +} + +.rounded-bottom { + border-bottom-right-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-left { + border-top-left-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-circle { + border-radius: 50% !important; +} + +.rounded-0 { + border-radius: 0 !important; +} + +.clearfix::after { + display: block; + clear: both; + content: ""; +} + +.d-none { + display: none !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; +} + +.d-inline-flex { + display: -webkit-inline-box !important; + display: -ms-inline-flexbox !important; + display: inline-flex !important; +} + +@media (min-width: 576px) { + .d-sm-none { + display: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + } + .d-sm-inline-flex { + display: -webkit-inline-box !important; + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 768px) { + .d-md-none { + display: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + } + .d-md-inline-flex { + display: -webkit-inline-box !important; + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 992px) { + .d-lg-none { + display: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + } + .d-lg-inline-flex { + display: -webkit-inline-box !important; + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 1200px) { + .d-xl-none { + display: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + } + .d-xl-inline-flex { + display: -webkit-inline-box !important; + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media print { + .d-print-none { + display: none !important; + } + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + } + .d-print-inline-flex { + display: -webkit-inline-box !important; + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +.embed-responsive { + position: relative; + display: block; + width: 100%; + padding: 0; + overflow: hidden; +} + +.embed-responsive::before { + display: block; + content: ""; +} + +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.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.8571428571%; +} + +.embed-responsive-16by9::before { + padding-top: 56.25%; +} + +.embed-responsive-4by3::before { + padding-top: 75%; +} + +.embed-responsive-1by1::before { + padding-top: 100%; +} + +.flex-row { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: row !important; + flex-direction: row !important; +} + +.flex-column { + -webkit-box-orient: vertical !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: column !important; + flex-direction: column !important; +} + +.flex-row-reverse { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + -webkit-box-orient: vertical !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; +} + +.flex-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; +} + +.flex-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; +} + +.flex-fill { + -webkit-box-flex: 1 !important; + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; +} + +.flex-grow-0 { + -webkit-box-flex: 0 !important; + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; +} + +.flex-grow-1 { + -webkit-box-flex: 1 !important; + -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 { + -webkit-box-pack: start !important; + -ms-flex-pack: start !important; + justify-content: flex-start !important; +} + +.justify-content-end { + -webkit-box-pack: end !important; + -ms-flex-pack: end !important; + justify-content: flex-end !important; +} + +.justify-content-center { + -webkit-box-pack: center !important; + -ms-flex-pack: center !important; + justify-content: center !important; +} + +.justify-content-between { + -webkit-box-pack: justify !important; + -ms-flex-pack: justify !important; + justify-content: space-between !important; +} + +.justify-content-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; +} + +.align-items-start { + -webkit-box-align: start !important; + -ms-flex-align: start !important; + align-items: flex-start !important; +} + +.align-items-end { + -webkit-box-align: end !important; + -ms-flex-align: end !important; + align-items: flex-end !important; +} + +.align-items-center { + -webkit-box-align: center !important; + -ms-flex-align: center !important; + align-items: center !important; +} + +.align-items-baseline { + -webkit-box-align: baseline !important; + -ms-flex-align: baseline !important; + align-items: baseline !important; +} + +.align-items-stretch { + -webkit-box-align: stretch !important; + -ms-flex-align: stretch !important; + align-items: stretch !important; +} + +.align-content-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; +} + +.align-content-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; +} + +.align-content-center { + -ms-flex-line-pack: center !important; + align-content: center !important; +} + +.align-content-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; +} + +.align-content-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; +} + +.align-content-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; +} + +.align-self-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; +} + +.align-self-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; +} + +.align-self-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; +} + +.align-self-center { + -ms-flex-item-align: center !important; + align-self: center !important; +} + +.align-self-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; +} + +.align-self-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; +} + +@media (min-width: 576px) { + .flex-sm-row { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-sm-column { + -webkit-box-orient: vertical !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-sm-row-reverse { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + -webkit-box-orient: vertical !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-sm-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-sm-fill { + -webkit-box-flex: 1 !important; + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-sm-grow-0 { + -webkit-box-flex: 0 !important; + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + -webkit-box-flex: 1 !important; + -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 { + -webkit-box-pack: start !important; + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-sm-end { + -webkit-box-pack: end !important; + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-sm-center { + -webkit-box-pack: center !important; + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-sm-between { + -webkit-box-pack: justify !important; + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-sm-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-sm-start { + -webkit-box-align: start !important; + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-sm-end { + -webkit-box-align: end !important; + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-sm-center { + -webkit-box-align: center !important; + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-sm-baseline { + -webkit-box-align: baseline !important; + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-sm-stretch { + -webkit-box-align: stretch !important; + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-sm-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-sm-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-sm-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-sm-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-sm-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-sm-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-sm-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-sm-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-sm-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-sm-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-sm-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-sm-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 768px) { + .flex-md-row { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-md-column { + -webkit-box-orient: vertical !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-md-row-reverse { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + -webkit-box-orient: vertical !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-md-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-md-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-md-fill { + -webkit-box-flex: 1 !important; + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-md-grow-0 { + -webkit-box-flex: 0 !important; + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-md-grow-1 { + -webkit-box-flex: 1 !important; + -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 { + -webkit-box-pack: start !important; + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-md-end { + -webkit-box-pack: end !important; + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-md-center { + -webkit-box-pack: center !important; + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-md-between { + -webkit-box-pack: justify !important; + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-md-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-md-start { + -webkit-box-align: start !important; + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-md-end { + -webkit-box-align: end !important; + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-md-center { + -webkit-box-align: center !important; + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-md-baseline { + -webkit-box-align: baseline !important; + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-md-stretch { + -webkit-box-align: stretch !important; + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-md-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-md-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-md-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-md-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-md-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-md-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-md-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-md-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-md-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-md-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-md-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-md-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 992px) { + .flex-lg-row { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-lg-column { + -webkit-box-orient: vertical !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-lg-row-reverse { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + -webkit-box-orient: vertical !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-lg-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-lg-fill { + -webkit-box-flex: 1 !important; + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-lg-grow-0 { + -webkit-box-flex: 0 !important; + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + -webkit-box-flex: 1 !important; + -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 { + -webkit-box-pack: start !important; + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-lg-end { + -webkit-box-pack: end !important; + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-lg-center { + -webkit-box-pack: center !important; + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-lg-between { + -webkit-box-pack: justify !important; + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-lg-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-lg-start { + -webkit-box-align: start !important; + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-lg-end { + -webkit-box-align: end !important; + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-lg-center { + -webkit-box-align: center !important; + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-lg-baseline { + -webkit-box-align: baseline !important; + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-lg-stretch { + -webkit-box-align: stretch !important; + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-lg-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-lg-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-lg-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-lg-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-lg-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-lg-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-lg-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-lg-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-lg-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-lg-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-lg-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-lg-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 1200px) { + .flex-xl-row { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-xl-column { + -webkit-box-orient: vertical !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-xl-row-reverse { + -webkit-box-orient: horizontal !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + -webkit-box-orient: vertical !important; + -webkit-box-direction: reverse !important; + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-xl-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-xl-fill { + -webkit-box-flex: 1 !important; + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-xl-grow-0 { + -webkit-box-flex: 0 !important; + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + -webkit-box-flex: 1 !important; + -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 { + -webkit-box-pack: start !important; + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-xl-end { + -webkit-box-pack: end !important; + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-xl-center { + -webkit-box-pack: center !important; + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-xl-between { + -webkit-box-pack: justify !important; + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-xl-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-xl-start { + -webkit-box-align: start !important; + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-xl-end { + -webkit-box-align: end !important; + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-xl-center { + -webkit-box-align: center !important; + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-xl-baseline { + -webkit-box-align: baseline !important; + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-xl-stretch { + -webkit-box-align: stretch !important; + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-xl-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-xl-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-xl-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-xl-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-xl-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-xl-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-xl-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-xl-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-xl-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-xl-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-xl-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-xl-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +.float-left { + float: left !important; +} + +.float-right { + float: right !important; +} + +.float-none { + float: none !important; +} + +@media (min-width: 576px) { + .float-sm-left { + float: left !important; + } + .float-sm-right { + float: right !important; + } + .float-sm-none { + float: none !important; + } +} + +@media (min-width: 768px) { + .float-md-left { + float: left !important; + } + .float-md-right { + float: right !important; + } + .float-md-none { + float: none !important; + } +} + +@media (min-width: 992px) { + .float-lg-left { + float: left !important; + } + .float-lg-right { + float: right !important; + } + .float-lg-none { + float: none !important; + } +} + +@media (min-width: 1200px) { + .float-xl-left { + float: left !important; + } + .float-xl-right { + float: right !important; + } + .float-xl-none { + float: none !important; + } +} + +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important; +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} + +@supports ((position: -webkit-sticky) or (position: sticky)) { + .sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + 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 { + -webkit-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +.shadow { + -webkit-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +.shadow-lg { + -webkit-box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} + +.shadow-none { + -webkit-box-shadow: none !important; + 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; +} + +.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: 0.25rem !important; +} + +.mt-1, +.my-1 { + margin-top: 0.25rem !important; +} + +.mr-1, +.mx-1 { + margin-right: 0.25rem !important; +} + +.mb-1, +.my-1 { + margin-bottom: 0.25rem !important; +} + +.ml-1, +.mx-1 { + margin-left: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.mt-2, +.my-2 { + margin-top: 0.5rem !important; +} + +.mr-2, +.mx-2 { + margin-right: 0.5rem !important; +} + +.mb-2, +.my-2 { + margin-bottom: 0.5rem !important; +} + +.ml-2, +.mx-2 { + margin-left: 0.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: 0.25rem !important; +} + +.pt-1, +.py-1 { + padding-top: 0.25rem !important; +} + +.pr-1, +.px-1 { + padding-right: 0.25rem !important; +} + +.pb-1, +.py-1 { + padding-bottom: 0.25rem !important; +} + +.pl-1, +.px-1 { + padding-left: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.pt-2, +.py-2 { + padding-top: 0.5rem !important; +} + +.pr-2, +.px-2 { + padding-right: 0.5rem !important; +} + +.pb-2, +.py-2 { + padding-bottom: 0.5rem !important; +} + +.pl-2, +.px-2 { + padding-left: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.pt-3, +.py-3 { + padding-top: 1rem !important; +} + +.pr-3, +.px-3 { + padding-right: 1rem !important; +} + +.pb-3, +.py-3 { + padding-bottom: 1rem !important; +} + +.pl-3, +.px-3 { + padding-left: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.pt-4, +.py-4 { + padding-top: 1.5rem !important; +} + +.pr-4, +.px-4 { + padding-right: 1.5rem !important; +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem !important; +} + +.pl-4, +.px-4 { + padding-left: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.pt-5, +.py-5 { + padding-top: 3rem !important; +} + +.pr-5, +.px-5 { + padding-right: 3rem !important; +} + +.pb-5, +.py-5 { + padding-bottom: 3rem !important; +} + +.pl-5, +.px-5 { + padding-left: 3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mt-auto, +.my-auto { + margin-top: auto !important; +} + +.mr-auto, +.mx-auto { + margin-right: auto !important; +} + +.mb-auto, +.my-auto { + margin-bottom: auto !important; +} + +.ml-auto, +.mx-auto { + margin-left: auto !important; +} + +@media (min-width: 576px) { + .m-sm-0 { + margin: 0 !important; + } + .mt-sm-0, + .my-sm-0 { + margin-top: 0 !important; + } + .mr-sm-0, + .mx-sm-0 { + margin-right: 0 !important; + } + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0 !important; + } + .ml-sm-0, + .mx-sm-0 { + margin-left: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .mt-sm-1, + .my-sm-1 { + margin-top: 0.25rem !important; + } + .mr-sm-1, + .mx-sm-1 { + margin-right: 0.25rem !important; + } + .mb-sm-1, + .my-sm-1 { + margin-bottom: 0.25rem !important; + } + .ml-sm-1, + .mx-sm-1 { + margin-left: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .mt-sm-2, + .my-sm-2 { + margin-top: 0.5rem !important; + } + .mr-sm-2, + .mx-sm-2 { + margin-right: 0.5rem !important; + } + .mb-sm-2, + .my-sm-2 { + margin-bottom: 0.5rem !important; + } + .ml-sm-2, + .mx-sm-2 { + margin-left: 0.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: 0.25rem !important; + } + .pt-sm-1, + .py-sm-1 { + padding-top: 0.25rem !important; + } + .pr-sm-1, + .px-sm-1 { + padding-right: 0.25rem !important; + } + .pb-sm-1, + .py-sm-1 { + padding-bottom: 0.25rem !important; + } + .pl-sm-1, + .px-sm-1 { + padding-left: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .pt-sm-2, + .py-sm-2 { + padding-top: 0.5rem !important; + } + .pr-sm-2, + .px-sm-2 { + padding-right: 0.5rem !important; + } + .pb-sm-2, + .py-sm-2 { + padding-bottom: 0.5rem !important; + } + .pl-sm-2, + .px-sm-2 { + padding-left: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem !important; + } + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem !important; + } + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem !important; + } + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem !important; + } + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem !important; + } + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem !important; + } + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem !important; + } + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem !important; + } + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mt-sm-auto, + .my-sm-auto { + margin-top: auto !important; + } + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto !important; + } + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto !important; + } + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto !important; + } +} + +@media (min-width: 768px) { + .m-md-0 { + margin: 0 !important; + } + .mt-md-0, + .my-md-0 { + margin-top: 0 !important; + } + .mr-md-0, + .mx-md-0 { + margin-right: 0 !important; + } + .mb-md-0, + .my-md-0 { + margin-bottom: 0 !important; + } + .ml-md-0, + .mx-md-0 { + margin-left: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .mt-md-1, + .my-md-1 { + margin-top: 0.25rem !important; + } + .mr-md-1, + .mx-md-1 { + margin-right: 0.25rem !important; + } + .mb-md-1, + .my-md-1 { + margin-bottom: 0.25rem !important; + } + .ml-md-1, + .mx-md-1 { + margin-left: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .mt-md-2, + .my-md-2 { + margin-top: 0.5rem !important; + } + .mr-md-2, + .mx-md-2 { + margin-right: 0.5rem !important; + } + .mb-md-2, + .my-md-2 { + margin-bottom: 0.5rem !important; + } + .ml-md-2, + .mx-md-2 { + margin-left: 0.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: 0.25rem !important; + } + .pt-md-1, + .py-md-1 { + padding-top: 0.25rem !important; + } + .pr-md-1, + .px-md-1 { + padding-right: 0.25rem !important; + } + .pb-md-1, + .py-md-1 { + padding-bottom: 0.25rem !important; + } + .pl-md-1, + .px-md-1 { + padding-left: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .pt-md-2, + .py-md-2 { + padding-top: 0.5rem !important; + } + .pr-md-2, + .px-md-2 { + padding-right: 0.5rem !important; + } + .pb-md-2, + .py-md-2 { + padding-bottom: 0.5rem !important; + } + .pl-md-2, + .px-md-2 { + padding-left: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .pt-md-3, + .py-md-3 { + padding-top: 1rem !important; + } + .pr-md-3, + .px-md-3 { + padding-right: 1rem !important; + } + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem !important; + } + .pl-md-3, + .px-md-3 { + padding-left: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem !important; + } + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem !important; + } + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem !important; + } + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .pt-md-5, + .py-md-5 { + padding-top: 3rem !important; + } + .pr-md-5, + .px-md-5 { + padding-right: 3rem !important; + } + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem !important; + } + .pl-md-5, + .px-md-5 { + padding-left: 3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mt-md-auto, + .my-md-auto { + margin-top: auto !important; + } + .mr-md-auto, + .mx-md-auto { + margin-right: auto !important; + } + .mb-md-auto, + .my-md-auto { + margin-bottom: auto !important; + } + .ml-md-auto, + .mx-md-auto { + margin-left: auto !important; + } +} + +@media (min-width: 992px) { + .m-lg-0 { + margin: 0 !important; + } + .mt-lg-0, + .my-lg-0 { + margin-top: 0 !important; + } + .mr-lg-0, + .mx-lg-0 { + margin-right: 0 !important; + } + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0 !important; + } + .ml-lg-0, + .mx-lg-0 { + margin-left: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .mt-lg-1, + .my-lg-1 { + margin-top: 0.25rem !important; + } + .mr-lg-1, + .mx-lg-1 { + margin-right: 0.25rem !important; + } + .mb-lg-1, + .my-lg-1 { + margin-bottom: 0.25rem !important; + } + .ml-lg-1, + .mx-lg-1 { + margin-left: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .mt-lg-2, + .my-lg-2 { + margin-top: 0.5rem !important; + } + .mr-lg-2, + .mx-lg-2 { + margin-right: 0.5rem !important; + } + .mb-lg-2, + .my-lg-2 { + margin-bottom: 0.5rem !important; + } + .ml-lg-2, + .mx-lg-2 { + margin-left: 0.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: 0.25rem !important; + } + .pt-lg-1, + .py-lg-1 { + padding-top: 0.25rem !important; + } + .pr-lg-1, + .px-lg-1 { + padding-right: 0.25rem !important; + } + .pb-lg-1, + .py-lg-1 { + padding-bottom: 0.25rem !important; + } + .pl-lg-1, + .px-lg-1 { + padding-left: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .pt-lg-2, + .py-lg-2 { + padding-top: 0.5rem !important; + } + .pr-lg-2, + .px-lg-2 { + padding-right: 0.5rem !important; + } + .pb-lg-2, + .py-lg-2 { + padding-bottom: 0.5rem !important; + } + .pl-lg-2, + .px-lg-2 { + padding-left: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem !important; + } + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem !important; + } + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem !important; + } + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem !important; + } + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem !important; + } + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem !important; + } + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem !important; + } + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem !important; + } + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mt-lg-auto, + .my-lg-auto { + margin-top: auto !important; + } + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto !important; + } + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto !important; + } + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto !important; + } +} + +@media (min-width: 1200px) { + .m-xl-0 { + margin: 0 !important; + } + .mt-xl-0, + .my-xl-0 { + margin-top: 0 !important; + } + .mr-xl-0, + .mx-xl-0 { + margin-right: 0 !important; + } + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0 !important; + } + .ml-xl-0, + .mx-xl-0 { + margin-left: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .mt-xl-1, + .my-xl-1 { + margin-top: 0.25rem !important; + } + .mr-xl-1, + .mx-xl-1 { + margin-right: 0.25rem !important; + } + .mb-xl-1, + .my-xl-1 { + margin-bottom: 0.25rem !important; + } + .ml-xl-1, + .mx-xl-1 { + margin-left: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .mt-xl-2, + .my-xl-2 { + margin-top: 0.5rem !important; + } + .mr-xl-2, + .mx-xl-2 { + margin-right: 0.5rem !important; + } + .mb-xl-2, + .my-xl-2 { + margin-bottom: 0.5rem !important; + } + .ml-xl-2, + .mx-xl-2 { + margin-left: 0.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: 0.25rem !important; + } + .pt-xl-1, + .py-xl-1 { + padding-top: 0.25rem !important; + } + .pr-xl-1, + .px-xl-1 { + padding-right: 0.25rem !important; + } + .pb-xl-1, + .py-xl-1 { + padding-bottom: 0.25rem !important; + } + .pl-xl-1, + .px-xl-1 { + padding-left: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .pt-xl-2, + .py-xl-2 { + padding-top: 0.5rem !important; + } + .pr-xl-2, + .px-xl-2 { + padding-right: 0.5rem !important; + } + .pb-xl-2, + .py-xl-2 { + padding-bottom: 0.5rem !important; + } + .pl-xl-2, + .px-xl-2 { + padding-left: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem !important; + } + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem !important; + } + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem !important; + } + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem !important; + } + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem !important; + } + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem !important; + } + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem !important; + } + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem !important; + } + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mt-xl-auto, + .my-xl-auto { + margin-top: auto !important; + } + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto !important; + } + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto !important; + } + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto !important; + } +} + +.text-monospace { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +.text-justify { + text-align: justify !important; +} + +.text-nowrap { + white-space: nowrap !important; +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.text-left { + text-align: left !important; +} + +.text-right { + text-align: right !important; +} + +.text-center { + text-align: center !important; +} + +@media (min-width: 576px) { + .text-sm-left { + text-align: left !important; + } + .text-sm-right { + text-align: right !important; + } + .text-sm-center { + text-align: center !important; + } +} + +@media (min-width: 768px) { + .text-md-left { + text-align: left !important; + } + .text-md-right { + text-align: right !important; + } + .text-md-center { + text-align: center !important; + } +} + +@media (min-width: 992px) { + .text-lg-left { + text-align: left !important; + } + .text-lg-right { + text-align: right !important; + } + .text-lg-center { + text-align: center !important; + } +} + +@media (min-width: 1200px) { + .text-xl-left { + text-align: left !important; + } + .text-xl-right { + text-align: right !important; + } + .text-xl-center { + text-align: center !important; + } +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.font-weight-light { + font-weight: 300 !important; +} + +.font-weight-normal { + font-weight: 400 !important; +} + +.font-weight-bold { + font-weight: 700 !important; +} + +.font-italic { + font-style: italic !important; +} + +.text-white { + color: #fff !important; +} + +.text-primary { + color: #325D88 !important; +} + +a.text-primary:hover, a.text-primary:focus { + color: #244463 !important; +} + +.text-secondary { + color: #8E8C84 !important; +} + +a.text-secondary:hover, a.text-secondary:focus { + color: #74726b !important; +} + +.text-success { + color: #93C54B !important; +} + +a.text-success:hover, a.text-success:focus { + color: #79a736 !important; +} + +.text-info { + color: #29ABE0 !important; +} + +a.text-info:hover, a.text-info:focus { + color: #1b8dbb !important; +} + +.text-warning { + color: #F47C3C !important; +} + +a.text-warning:hover, a.text-warning:focus { + color: #ef5c0e !important; +} + +.text-danger { + color: #d9534f !important; +} + +a.text-danger:hover, a.text-danger:focus { + color: #c9302c !important; +} + +.text-light { + color: #F8F5F0 !important; +} + +a.text-light:hover, a.text-light:focus { + color: #e8decd !important; +} + +.text-dark { + color: #3E3F3A !important; +} + +a.text-dark:hover, a.text-dark:focus { + color: #242422 !important; +} + +.text-body { + color: #3E3F3A !important; +} + +.text-muted { + color: #8E8C84 !important; +} + +.text-black-50 { + color: rgba(0, 0, 0, 0.5) !important; +} + +.text-white-50 { + color: rgba(255, 255, 255, 0.5) !important; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.visible { + visibility: visible !important; +} + +.invisible { + visibility: hidden !important; +} + +@media print { + *, + *::before, + *::after { + text-shadow: none !important; + -webkit-box-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; + } + pre, + blockquote { + border: 1px solid #98978B; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + p, + h2, + h3 { + 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 th, + .table-bordered td { + border: 1px solid #DFD7CA !important; + } + .table-dark { + color: inherit; + } + .table-dark th, + .table-dark td, + .table-dark thead th, + .table-dark tbody + tbody { + border-color: #DFD7CA; + } + .table .thead-dark th { + color: inherit; + border-color: #DFD7CA; + } +} + +.bg-primary { + background-color: #3E3F3A !important; +} + +.bg-dark { + background-color: #3E3F3A !important; +} + +.bg-light { + background-color: #F8F5F0 !important; +} + +.sandstone, .navbar .nav-link, .btn, .nav-tabs .nav-link, .nav-pills .nav-link, .breadcrumb, .pagination, .dropdown-menu .dropdown-item, .tooltip { + font-size: 11px; + line-height: 22px; + font-weight: 500; + text-transform: uppercase; +} + +.navbar-form input, +.navbar-form .form-control { + border: none; +} + +.btn:hover { + border-color: transparent; +} + +.btn-success, .btn-warning { + color: #fff; +} + +.table .thead-dark th { + background-color: #3E3F3A; +} + +.nav-tabs .nav-link { + background-color: #F8F5F0; + border-color: #DFD7CA; +} + +.nav-tabs .nav-link, +.nav-tabs .nav-link:hover, +.nav-tabs .nav-link:focus { + color: #8E8C84; +} + +.nav-tabs .nav-link.disabled, +.nav-tabs .nav-link.disabled:hover, +.nav-tabs .nav-link.disabled:focus { + background-color: #F8F5F0; + border-color: #DFD7CA; + color: #DFD7CA; +} + +.nav-pills .nav-link { + border: 1px solid transparent; + color: #8E8C84; +} + +.nav-pills .nav-link.active, +.nav-pills .nav-link:hover, +.nav-pills .nav-link:focus { + background-color: #F8F5F0; + border-color: #DFD7CA; +} + +.nav-pills .nav-link.disabled, +.nav-pills .nav-link.disabled:hover { + background-color: transparent; + border-color: transparent; + color: #DFD7CA; +} + +.breadcrumb { + border: 1px solid #DFD7CA; +} + +.pagination a:hover { + text-decoration: none; +} + +.alert { + color: #fff; +} + +.alert a, +.alert .alert-link { + color: #fff; + text-decoration: underline; +} + +.alert-primary, .alert-primary > th, .alert-primary > td { + background-color: #325D88; +} + +.alert-secondary, .alert-secondary > th, .alert-secondary > td { + background-color: #8E8C84; +} + +.alert-success, .alert-success > th, .alert-success > td { + background-color: #93C54B; +} + +.alert-info, .alert-info > th, .alert-info > td { + background-color: #29ABE0; +} + +.alert-danger, .alert-danger > th, .alert-danger > td { + background-color: #d9534f; +} + +.alert-warning, .alert-warning > th, .alert-warning > td { + background-color: #F47C3C; +} + +.alert-dark, .alert-dark > th, .alert-dark > td { + background-color: #3E3F3A; +} + +.alert-light, .alert-light > th, .alert-light > td { + background-color: #F8F5F0; +} + +.alert-light, +.alert-light a:not(.btn), +.alert-light .alert-link { + color: #3E3F3A; +} + +.badge-success, .badge-warning { + color: #fff; +} + +.close { + color: #DFD7CA; + opacity: 1; +} + +.close:hover { + color: #b9a78a; +} + +footer { + color: white; } +footer h3 { + margin-bottom: 30px; } +footer .footer-above { + padding-top: 50px; + background-color: #3E3F3A; } +footer .footer-col { + margin-bottom: 50px; } +footer .footer-below { + padding: 25px 0; + background-color: #3E3F3A; } + + +.btn-social { + font-size: 20px; + line-height: 45px; + display: inline-block; + width: 50px; + height: 50px; + text-align: center; + border: 2px solid white; + border-radius: 100%; } + +.btn-outline { + font-size: 20px; + margin-top: 15px; + transition: all 0.3s ease-in-out; + color: white; + border: solid 2px white; + background: transparent; } +.btn-outline.active, .btn-outline:active, .btn-outline:focus, .btn-outline:hover { + color: #18BC9C; + border: solid 2px white; + background: white; } + + +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.fa-fw { + width: 1.28571429em; + text-align: center; +} + +.fa-wordpress:before { + content: "\f19a"; +} + +.fa-github:before { + content: "\f09b"; +} + +.fa-github-square:before { + content: "\f092"; +} + +.fa-wordpress:before { + content: "\f19a"; +} + +.fa-youtube:before { + content: "\f167"; +} \ No newline at end of file diff --git a/blogContent/projects/steam/css/bootstrap.min.css b/blogContent/projects/steam/css/bootstrap.min.css new file mode 100644 index 0000000..1a7e64c --- /dev/null +++ b/blogContent/projects/steam/css/bootstrap.min.css @@ -0,0 +1,12 @@ +/*! + * Bootswatch v4.1.1 + * Homepage: https://bootswatch.com + * Copyright 2012-2018 Thomas Park + * Licensed under MIT + * Based on Bootstrap +*//*! + * Bootstrap v4.1.1 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */@import url("https://fonts.googleapis.com/css?family=Roboto:400,500,700");:root{--blue:#325D88;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#d9534f;--orange:#F47C3C;--yellow:#ffc107;--green:#93C54B;--teal:#20c997;--cyan:#29ABE0;--white:#fff;--gray:#8E8C84;--gray-dark:#3E3F3A;--primary:#325D88;--secondary:#8E8C84;--success:#93C54B;--info:#29ABE0;--warning:#F47C3C;--danger:#d9534f;--light:#F8F5F0;--dark:#3E3F3A;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:"Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";--font-family-monospace:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{-webkit-box-sizing:border-box;box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:"Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size:0.875rem;font-weight:400;line-height:1.5;color:#3E3F3A;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0 !important}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:0.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#93C54B;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#6b9430;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):hover,a:not([href]):not([tabindex]):focus{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre,code,kbd,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;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}table{border-collapse:collapse}caption{padding-top:0.75rem;padding-bottom:0.75rem;color:#8E8C84;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:0.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{padding:0;border-style:none}input[type="radio"],input[type="checkbox"]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="date"],input[type="time"],input[type="datetime-local"],input[type="month"]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{outline-offset:-2px;-webkit-appearance:none}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none !important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:0.5rem;font-family:inherit;font-weight:400;line-height:1.2;color:inherit}h1,.h1{font-size:2.1875rem}h2,.h2{font-size:1.75rem}h3,.h3{font-size:1.53125rem}h4,.h4{font-size:1.3125rem}h5,.h5{font-size:1.09375rem}h6,.h6{font-size:0.875rem}.lead{font-size:1.09375rem;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,0.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:0.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:0.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.09375rem}.blockquote-footer{display:block;font-size:80%;color:#8E8C84}.blockquote-footer::before{content:"\2014 \00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:0.25rem;background-color:#fff;border:1px solid #DFD7CA;border-radius:0.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:0.5rem;line-height:1}.figure-caption{font-size:90%;color:#8E8C84}code{font-size:87.5%;color:#e83e8c;word-break:break-word}a>code{color:inherit}kbd{padding:0.2rem 0.4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:0.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container{max-width:540px}}@media (min-width: 768px){.container{max-width:720px}}@media (min-width: 992px){.container{max-width:960px}}@media (min-width: 1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*="col-"]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.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-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.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-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.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-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.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-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}@media (min-width: 576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-sm-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-sm-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-sm-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-sm-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-sm-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-sm-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-sm-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}}@media (min-width: 768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-md-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-md-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-md-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-md-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-md-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-md-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-md-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}}@media (min-width: 992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-lg-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-lg-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-lg-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-lg-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-lg-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-lg-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-lg-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}}@media (min-width: 1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-xl-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-xl-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-xl-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-xl-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-xl-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-xl-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-xl-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}}.table{width:100%;max-width:100%;margin-bottom:1rem;background-color:transparent}.table th,.table td{padding:0.75rem;vertical-align:top;border-top:1px solid #DFD7CA}.table thead th{vertical-align:bottom;border-bottom:2px solid #DFD7CA}.table tbody+tbody{border-top:2px solid #DFD7CA}.table .table{background-color:#fff}.table-sm th,.table-sm td{padding:0.3rem}.table-bordered{border:1px solid #DFD7CA}.table-bordered th,.table-bordered td{border:1px solid #DFD7CA}.table-bordered thead th,.table-bordered thead td{border-bottom-width:2px}.table-borderless th,.table-borderless td,.table-borderless thead th,.table-borderless tbody+tbody{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,0.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,0.075)}.table-primary,.table-primary>th,.table-primary>td{background-color:#c6d2de}.table-hover .table-primary:hover{background-color:#b6c5d5}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#b6c5d5}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#dfdfdd}.table-hover .table-secondary:hover{background-color:#d3d3d0}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#d3d3d0}.table-success,.table-success>th,.table-success>td{background-color:#e1efcd}.table-hover .table-success:hover{background-color:#d5e9ba}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#d5e9ba}.table-info,.table-info>th,.table-info>td{background-color:#c3e7f6}.table-hover .table-info:hover{background-color:#addef3}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#addef3}.table-warning,.table-warning>th,.table-warning>td{background-color:#fcdac8}.table-hover .table-warning:hover{background-color:#fbcab0}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#fbcab0}.table-danger,.table-danger>th,.table-danger>td{background-color:#f4cfce}.table-hover .table-danger:hover{background-color:#efbbb9}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#efbbb9}.table-light,.table-light>th,.table-light>td{background-color:#fdfcfb}.table-hover .table-light:hover{background-color:#f5efea}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#f5efea}.table-dark,.table-dark>th,.table-dark>td{background-color:#c9c9c8}.table-hover .table-dark:hover{background-color:#bcbcbb}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#bcbcbb}.table-active,.table-active>th,.table-active>td{background-color:rgba(0,0,0,0.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,0.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,0.075)}.table .thead-dark th{color:#fff;background-color:#212529;border-color:#32383e}.table .thead-light th{color:#495057;background-color:#F8F5F0;border-color:#DFD7CA}.table-dark{color:#fff;background-color:#212529}.table-dark th,.table-dark td,.table-dark thead th{border-color:#32383e}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,0.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,0.075)}@media (max-width: 575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm>.table-bordered{border:0}}@media (max-width: 767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md>.table-bordered{border:0}}@media (max-width: 991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg>.table-bordered{border:0}}@media (max-width: 1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;padding:0.375rem 0.75rem;font-size:0.875rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:0.25rem;-webkit-transition:border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media screen and (prefers-reduced-motion: reduce){.form-control{-webkit-transition:none;transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#6f9dca;outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(50,93,136,0.25);box-shadow:0 0 0 0.2rem rgba(50,93,136,0.25)}.form-control::-webkit-input-placeholder{color:#8E8C84;opacity:1}.form-control:-ms-input-placeholder{color:#8E8C84;opacity:1}.form-control::-ms-input-placeholder{color:#8E8C84;opacity:1}.form-control::placeholder{color:#8E8C84;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#F8F5F0;opacity:1}select.form-control:not([size]):not([multiple]){height:calc(2.0625rem + 2px)}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.09375rem;line-height:1.5}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.765625rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:0.375rem;padding-bottom:0.375rem;margin-bottom:0;line-height:1.5;color:#3E3F3A;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.input-group-sm>.form-control-plaintext.form-control,.input-group-sm>.input-group-prepend>.form-control-plaintext.input-group-text,.input-group-sm>.input-group-append>.form-control-plaintext.input-group-text,.input-group-sm>.input-group-prepend>.form-control-plaintext.btn,.input-group-sm>.input-group-append>.form-control-plaintext.btn,.form-control-plaintext.form-control-lg,.input-group-lg>.form-control-plaintext.form-control,.input-group-lg>.input-group-prepend>.form-control-plaintext.input-group-text,.input-group-lg>.input-group-append>.form-control-plaintext.input-group-text,.input-group-lg>.input-group-prepend>.form-control-plaintext.btn,.input-group-lg>.input-group-append>.form-control-plaintext.btn{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-prepend>.input-group-text,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-append>.btn{padding:0.25rem 0.5rem;font-size:0.765625rem;line-height:1.5;border-radius:0.2rem}select.form-control-sm:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),.input-group-sm>.input-group-prepend>select.input-group-text:not([size]):not([multiple]),.input-group-sm>.input-group-append>select.input-group-text:not([size]):not([multiple]),.input-group-sm>.input-group-prepend>select.btn:not([size]):not([multiple]),.input-group-sm>.input-group-append>select.btn:not([size]):not([multiple]){height:calc(1.6484375rem + 2px)}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-prepend>.input-group-text,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-append>.btn{padding:0.5rem 1rem;font-size:1.09375rem;line-height:1.5;border-radius:0.3rem}select.form-control-lg:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),.input-group-lg>.input-group-prepend>select.input-group-text:not([size]):not([multiple]),.input-group-lg>.input-group-append>select.input-group-text:not([size]):not([multiple]),.input-group-lg>.input-group-prepend>select.btn:not([size]):not([multiple]),.input-group-lg>.input-group-append>select.btn:not([size]):not([multiple]){height:calc(2.640625rem + 2px)}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:0.25rem}.form-row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*="col-"]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:0.3rem;margin-left:-1.25rem}.form-check-input:disabled ~ .form-check-label{color:#8E8C84}.form-check-label{margin-bottom:0}.form-check-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:0.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:0.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:0.25rem;font-size:80%;color:#93C54B}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.5rem;margin-top:.1rem;font-size:.875rem;line-height:1;color:#fff;background-color:rgba(147,197,75,0.8);border-radius:.2rem}.was-validated .form-control:valid,.form-control.is-valid,.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#93C54B}.was-validated .form-control:valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#93C54B;-webkit-box-shadow:0 0 0 0.2rem rgba(147,197,75,0.25);box-shadow:0 0 0 0.2rem rgba(147,197,75,0.25)}.was-validated .form-control:valid ~ .valid-feedback,.was-validated .form-control:valid ~ .valid-tooltip,.form-control.is-valid ~ .valid-feedback,.form-control.is-valid ~ .valid-tooltip,.was-validated .custom-select:valid ~ .valid-feedback,.was-validated .custom-select:valid ~ .valid-tooltip,.custom-select.is-valid ~ .valid-feedback,.custom-select.is-valid ~ .valid-tooltip{display:block}.was-validated .form-control-file:valid ~ .valid-feedback,.was-validated .form-control-file:valid ~ .valid-tooltip,.form-control-file.is-valid ~ .valid-feedback,.form-control-file.is-valid ~ .valid-tooltip{display:block}.was-validated .form-check-input:valid ~ .form-check-label,.form-check-input.is-valid ~ .form-check-label{color:#93C54B}.was-validated .form-check-input:valid ~ .valid-feedback,.was-validated .form-check-input:valid ~ .valid-tooltip,.form-check-input.is-valid ~ .valid-feedback,.form-check-input.is-valid ~ .valid-tooltip{display:block}.was-validated .custom-control-input:valid ~ .custom-control-label,.custom-control-input.is-valid ~ .custom-control-label{color:#93C54B}.was-validated .custom-control-input:valid ~ .custom-control-label::before,.custom-control-input.is-valid ~ .custom-control-label::before{background-color:#cde4ab}.was-validated .custom-control-input:valid ~ .valid-feedback,.was-validated .custom-control-input:valid ~ .valid-tooltip,.custom-control-input.is-valid ~ .valid-feedback,.custom-control-input.is-valid ~ .valid-tooltip{display:block}.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before,.custom-control-input.is-valid:checked ~ .custom-control-label::before{background-color:#aad172}.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before,.custom-control-input.is-valid:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(147,197,75,0.25);box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(147,197,75,0.25)}.was-validated .custom-file-input:valid ~ .custom-file-label,.custom-file-input.is-valid ~ .custom-file-label{border-color:#93C54B}.was-validated .custom-file-input:valid ~ .custom-file-label::before,.custom-file-input.is-valid ~ .custom-file-label::before{border-color:inherit}.was-validated .custom-file-input:valid ~ .valid-feedback,.was-validated .custom-file-input:valid ~ .valid-tooltip,.custom-file-input.is-valid ~ .valid-feedback,.custom-file-input.is-valid ~ .valid-tooltip{display:block}.was-validated .custom-file-input:valid:focus ~ .custom-file-label,.custom-file-input.is-valid:focus ~ .custom-file-label{-webkit-box-shadow:0 0 0 0.2rem rgba(147,197,75,0.25);box-shadow:0 0 0 0.2rem rgba(147,197,75,0.25)}.invalid-feedback{display:none;width:100%;margin-top:0.25rem;font-size:80%;color:#d9534f}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.5rem;margin-top:.1rem;font-size:.875rem;line-height:1;color:#fff;background-color:rgba(217,83,79,0.8);border-radius:.2rem}.was-validated .form-control:invalid,.form-control.is-invalid,.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#d9534f}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#d9534f;-webkit-box-shadow:0 0 0 0.2rem rgba(217,83,79,0.25);box-shadow:0 0 0 0.2rem rgba(217,83,79,0.25)}.was-validated .form-control:invalid ~ .invalid-feedback,.was-validated .form-control:invalid ~ .invalid-tooltip,.form-control.is-invalid ~ .invalid-feedback,.form-control.is-invalid ~ .invalid-tooltip,.was-validated .custom-select:invalid ~ .invalid-feedback,.was-validated .custom-select:invalid ~ .invalid-tooltip,.custom-select.is-invalid ~ .invalid-feedback,.custom-select.is-invalid ~ .invalid-tooltip{display:block}.was-validated .form-control-file:invalid ~ .invalid-feedback,.was-validated .form-control-file:invalid ~ .invalid-tooltip,.form-control-file.is-invalid ~ .invalid-feedback,.form-control-file.is-invalid ~ .invalid-tooltip{display:block}.was-validated .form-check-input:invalid ~ .form-check-label,.form-check-input.is-invalid ~ .form-check-label{color:#d9534f}.was-validated .form-check-input:invalid ~ .invalid-feedback,.was-validated .form-check-input:invalid ~ .invalid-tooltip,.form-check-input.is-invalid ~ .invalid-feedback,.form-check-input.is-invalid ~ .invalid-tooltip{display:block}.was-validated .custom-control-input:invalid ~ .custom-control-label,.custom-control-input.is-invalid ~ .custom-control-label{color:#d9534f}.was-validated .custom-control-input:invalid ~ .custom-control-label::before,.custom-control-input.is-invalid ~ .custom-control-label::before{background-color:#f0b9b8}.was-validated .custom-control-input:invalid ~ .invalid-feedback,.was-validated .custom-control-input:invalid ~ .invalid-tooltip,.custom-control-input.is-invalid ~ .invalid-feedback,.custom-control-input.is-invalid ~ .invalid-tooltip{display:block}.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before,.custom-control-input.is-invalid:checked ~ .custom-control-label::before{background-color:#e27c79}.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before,.custom-control-input.is-invalid:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(217,83,79,0.25);box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(217,83,79,0.25)}.was-validated .custom-file-input:invalid ~ .custom-file-label,.custom-file-input.is-invalid ~ .custom-file-label{border-color:#d9534f}.was-validated .custom-file-input:invalid ~ .custom-file-label::before,.custom-file-input.is-invalid ~ .custom-file-label::before{border-color:inherit}.was-validated .custom-file-input:invalid ~ .invalid-feedback,.was-validated .custom-file-input:invalid ~ .invalid-tooltip,.custom-file-input.is-invalid ~ .invalid-feedback,.custom-file-input.is-invalid ~ .invalid-tooltip{display:block}.was-validated .custom-file-input:invalid:focus ~ .custom-file-label,.custom-file-input.is-invalid:focus ~ .custom-file-label{-webkit-box-shadow:0 0 0 0.2rem rgba(217,83,79,0.25);box-shadow:0 0 0 0.2rem rgba(217,83,79,0.25)}.form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width: 576px){.form-inline label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:0.25rem;margin-left:0}.form-inline .custom-control{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:0.375rem 0.75rem;font-size:0.875rem;line-height:1.5;border-radius:0.25rem;-webkit-transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;transition:color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-box-shadow 0.15s ease-in-out}@media screen and (prefers-reduced-motion: reduce){.btn{-webkit-transition:none;transition:none}}.btn:hover,.btn:focus{text-decoration:none}.btn:focus,.btn.focus{outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(50,93,136,0.25);box-shadow:0 0 0 0.2rem rgba(50,93,136,0.25)}.btn.disabled,.btn:disabled{opacity:0.65}.btn:not(:disabled):not(.disabled){cursor:pointer}.btn:not(:disabled):not(.disabled):active,.btn:not(:disabled):not(.disabled).active{background-image:none}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#325D88;border-color:#325D88}.btn-primary:hover{color:#fff;background-color:#284a6c;border-color:#244463}.btn-primary:focus,.btn-primary.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(50,93,136,0.5);box-shadow:0 0 0 0.2rem rgba(50,93,136,0.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#325D88;border-color:#325D88}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#244463;border-color:#213d59}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(50,93,136,0.5);box-shadow:0 0 0 0.2rem rgba(50,93,136,0.5)}.btn-secondary{color:#fff;background-color:#8E8C84;border-color:#8E8C84}.btn-secondary:hover{color:#fff;background-color:#7b7971;border-color:#74726b}.btn-secondary:focus,.btn-secondary.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(142,140,132,0.5);box-shadow:0 0 0 0.2rem rgba(142,140,132,0.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#8E8C84;border-color:#8E8C84}.btn-secondary:not(:disabled):not(.disabled):active,.btn-secondary:not(:disabled):not(.disabled).active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#74726b;border-color:#6e6c65}.btn-secondary:not(:disabled):not(.disabled):active:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-secondary.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(142,140,132,0.5);box-shadow:0 0 0 0.2rem rgba(142,140,132,0.5)}.btn-success{color:#fff;background-color:#93C54B;border-color:#93C54B}.btn-success:hover{color:#fff;background-color:#80b139;border-color:#79a736}.btn-success:focus,.btn-success.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(147,197,75,0.5);box-shadow:0 0 0 0.2rem rgba(147,197,75,0.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#93C54B;border-color:#93C54B}.btn-success:not(:disabled):not(.disabled):active,.btn-success:not(:disabled):not(.disabled).active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#79a736;border-color:#729e33}.btn-success:not(:disabled):not(.disabled):active:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.show>.btn-success.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(147,197,75,0.5);box-shadow:0 0 0 0.2rem rgba(147,197,75,0.5)}.btn-info{color:#fff;background-color:#29ABE0;border-color:#29ABE0}.btn-info:hover{color:#fff;background-color:#1d95c6;border-color:#1b8dbb}.btn-info:focus,.btn-info.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(41,171,224,0.5);box-shadow:0 0 0 0.2rem rgba(41,171,224,0.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#29ABE0;border-color:#29ABE0}.btn-info:not(:disabled):not(.disabled):active,.btn-info:not(:disabled):not(.disabled).active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#1b8dbb;border-color:#1984b0}.btn-info:not(:disabled):not(.disabled):active:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.show>.btn-info.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(41,171,224,0.5);box-shadow:0 0 0 0.2rem rgba(41,171,224,0.5)}.btn-warning{color:#fff;background-color:#F47C3C;border-color:#F47C3C}.btn-warning:hover{color:#fff;background-color:#f26418;border-color:#ef5c0e}.btn-warning:focus,.btn-warning.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(244,124,60,0.5);box-shadow:0 0 0 0.2rem rgba(244,124,60,0.5)}.btn-warning.disabled,.btn-warning:disabled{color:#fff;background-color:#F47C3C;border-color:#F47C3C}.btn-warning:not(:disabled):not(.disabled):active,.btn-warning:not(:disabled):not(.disabled).active,.show>.btn-warning.dropdown-toggle{color:#fff;background-color:#ef5c0e;border-color:#e3570d}.btn-warning:not(:disabled):not(.disabled):active:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-warning.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(244,124,60,0.5);box-shadow:0 0 0 0.2rem rgba(244,124,60,0.5)}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-danger:hover{color:#fff;background-color:#d23430;border-color:#c9302c}.btn-danger:focus,.btn-danger.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(217,83,79,0.5);box-shadow:0 0 0 0.2rem rgba(217,83,79,0.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-danger:not(:disabled):not(.disabled):active,.btn-danger:not(:disabled):not(.disabled).active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;border-color:#bf2e29}.btn-danger:not(:disabled):not(.disabled):active:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-danger.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(217,83,79,0.5);box-shadow:0 0 0 0.2rem rgba(217,83,79,0.5)}.btn-light{color:#212529;background-color:#F8F5F0;border-color:#F8F5F0}.btn-light:hover{color:#212529;background-color:#ece4d6;border-color:#e8decd}.btn-light:focus,.btn-light.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(248,245,240,0.5);box-shadow:0 0 0 0.2rem rgba(248,245,240,0.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#F8F5F0;border-color:#F8F5F0}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#e8decd;border-color:#e4d8c5}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(248,245,240,0.5);box-shadow:0 0 0 0.2rem rgba(248,245,240,0.5)}.btn-dark{color:#fff;background-color:#3E3F3A;border-color:#3E3F3A}.btn-dark:hover{color:#fff;background-color:#2a2b28;border-color:#242422}.btn-dark:focus,.btn-dark.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(62,63,58,0.5);box-shadow:0 0 0 0.2rem rgba(62,63,58,0.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#3E3F3A;border-color:#3E3F3A}.btn-dark:not(:disabled):not(.disabled):active,.btn-dark:not(:disabled):not(.disabled).active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#242422;border-color:#1d1e1b}.btn-dark:not(:disabled):not(.disabled):active:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-dark.dropdown-toggle:focus{-webkit-box-shadow:0 0 0 0.2rem rgba(62,63,58,0.5);box-shadow:0 0 0 0.2rem rgba(62,63,58,0.5)}.btn-outline-primary{color:#325D88;background-color:transparent;background-image:none;border-color:#325D88}.btn-outline-primary:hover{color:#fff;background-color:#325D88;border-color:#325D88}.btn-outline-primary:focus,.btn-outline-primary.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(50,93,136,0.5);box-shadow:0 0 0 0.2rem rgba(50,93,136,0.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#325D88;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:#325D88;border-color:#325D88}.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{-webkit-box-shadow:0 0 0 0.2rem rgba(50,93,136,0.5);box-shadow:0 0 0 0.2rem rgba(50,93,136,0.5)}.btn-outline-secondary{color:#8E8C84;background-color:transparent;background-image:none;border-color:#8E8C84}.btn-outline-secondary:hover{color:#fff;background-color:#8E8C84;border-color:#8E8C84}.btn-outline-secondary:focus,.btn-outline-secondary.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(142,140,132,0.5);box-shadow:0 0 0 0.2rem rgba(142,140,132,0.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#8E8C84;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:#8E8C84;border-color:#8E8C84}.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{-webkit-box-shadow:0 0 0 0.2rem rgba(142,140,132,0.5);box-shadow:0 0 0 0.2rem rgba(142,140,132,0.5)}.btn-outline-success{color:#93C54B;background-color:transparent;background-image:none;border-color:#93C54B}.btn-outline-success:hover{color:#fff;background-color:#93C54B;border-color:#93C54B}.btn-outline-success:focus,.btn-outline-success.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(147,197,75,0.5);box-shadow:0 0 0 0.2rem rgba(147,197,75,0.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#93C54B;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:#93C54B;border-color:#93C54B}.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{-webkit-box-shadow:0 0 0 0.2rem rgba(147,197,75,0.5);box-shadow:0 0 0 0.2rem rgba(147,197,75,0.5)}.btn-outline-info{color:#29ABE0;background-color:transparent;background-image:none;border-color:#29ABE0}.btn-outline-info:hover{color:#fff;background-color:#29ABE0;border-color:#29ABE0}.btn-outline-info:focus,.btn-outline-info.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(41,171,224,0.5);box-shadow:0 0 0 0.2rem rgba(41,171,224,0.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#29ABE0;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:#29ABE0;border-color:#29ABE0}.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{-webkit-box-shadow:0 0 0 0.2rem rgba(41,171,224,0.5);box-shadow:0 0 0 0.2rem rgba(41,171,224,0.5)}.btn-outline-warning{color:#F47C3C;background-color:transparent;background-image:none;border-color:#F47C3C}.btn-outline-warning:hover{color:#fff;background-color:#F47C3C;border-color:#F47C3C}.btn-outline-warning:focus,.btn-outline-warning.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(244,124,60,0.5);box-shadow:0 0 0 0.2rem rgba(244,124,60,0.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#F47C3C;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:#fff;background-color:#F47C3C;border-color:#F47C3C}.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{-webkit-box-shadow:0 0 0 0.2rem rgba(244,124,60,0.5);box-shadow:0 0 0 0.2rem rgba(244,124,60,0.5)}.btn-outline-danger{color:#d9534f;background-color:transparent;background-image:none;border-color:#d9534f}.btn-outline-danger:hover{color:#fff;background-color:#d9534f;border-color:#d9534f}.btn-outline-danger:focus,.btn-outline-danger.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(217,83,79,0.5);box-shadow:0 0 0 0.2rem rgba(217,83,79,0.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#d9534f;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:#d9534f;border-color:#d9534f}.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{-webkit-box-shadow:0 0 0 0.2rem rgba(217,83,79,0.5);box-shadow:0 0 0 0.2rem rgba(217,83,79,0.5)}.btn-outline-light{color:#F8F5F0;background-color:transparent;background-image:none;border-color:#F8F5F0}.btn-outline-light:hover{color:#212529;background-color:#F8F5F0;border-color:#F8F5F0}.btn-outline-light:focus,.btn-outline-light.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(248,245,240,0.5);box-shadow:0 0 0 0.2rem rgba(248,245,240,0.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#F8F5F0;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:#F8F5F0;border-color:#F8F5F0}.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{-webkit-box-shadow:0 0 0 0.2rem rgba(248,245,240,0.5);box-shadow:0 0 0 0.2rem rgba(248,245,240,0.5)}.btn-outline-dark{color:#3E3F3A;background-color:transparent;background-image:none;border-color:#3E3F3A}.btn-outline-dark:hover{color:#fff;background-color:#3E3F3A;border-color:#3E3F3A}.btn-outline-dark:focus,.btn-outline-dark.focus{-webkit-box-shadow:0 0 0 0.2rem rgba(62,63,58,0.5);box-shadow:0 0 0 0.2rem rgba(62,63,58,0.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#3E3F3A;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:#3E3F3A;border-color:#3E3F3A}.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{-webkit-box-shadow:0 0 0 0.2rem rgba(62,63,58,0.5);box-shadow:0 0 0 0.2rem rgba(62,63,58,0.5)}.btn-link{font-weight:400;color:#93C54B;background-color:transparent}.btn-link:hover{color:#6b9430;text-decoration:underline;background-color:transparent;border-color:transparent}.btn-link:focus,.btn-link.focus{text-decoration:underline;border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link:disabled,.btn-link.disabled{color:#8E8C84;pointer-events:none}.btn-lg,.btn-group-lg>.btn{padding:0.5rem 1rem;font-size:1.09375rem;line-height:1.5;border-radius:0.3rem}.btn-sm,.btn-group-sm>.btn{padding:0.25rem 0.5rem;font-size:0.765625rem;line-height:1.5;border-radius:0.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:0.5rem}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{-webkit-transition:opacity 0.15s linear;transition:opacity 0.15s linear}@media screen and (prefers-reduced-motion: reduce){.fade{-webkit-transition:none;transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height 0.35s ease;transition:height 0.35s ease}@media screen and (prefers-reduced-motion: reduce){.collapsing{-webkit-transition:none;transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid;border-right:0.3em solid transparent;border-bottom:0;border-left:0.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:0.5rem 0;margin:0.125rem 0 0;font-size:0.875rem;color:#3E3F3A;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,0.15);border-radius:0.25rem}.dropdown-menu-right{right:0;left:auto}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:0.125rem}.dropup .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0;border-right:0.3em solid transparent;border-bottom:0.3em solid;border-left:0.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:0.125rem}.dropright .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid transparent;border-right:0;border-bottom:0.3em solid transparent;border-left:0.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:0.125rem}.dropleft .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:0.255em;vertical-align:0.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;width:0;height:0;margin-right:0.255em;vertical-align:0.255em;content:"";border-top:0.3em solid transparent;border-right:0.3em solid;border-bottom:0.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^="top"],.dropdown-menu[x-placement^="right"],.dropdown-menu[x-placement^="bottom"],.dropdown-menu[x-placement^="left"]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:0.5rem 0;overflow:hidden;border-top:1px solid #F8F5F0}.dropdown-item{display:block;width:100%;padding:0.25rem 1.5rem;clear:both;font-weight:400;color:#8E8C84;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-item:focus{color:#8E8C84;text-decoration:none;background-color:#F8F5F0}.dropdown-item.active,.dropdown-item:active{color:#8E8C84;text-decoration:none;background-color:#F8F5F0}.dropdown-item.disabled,.dropdown-item:disabled{color:#8E8C84;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:0.5rem 1.5rem;margin-bottom:0;font-size:0.765625rem;color:#8E8C84;white-space:nowrap}.dropdown-item-text{display:block;padding:0.25rem 1.5rem;color:#8E8C84}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover{z-index:1}.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:0.5625rem;padding-left:0.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:0.375rem;padding-left:0.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:0.75rem;padding-left:0.75rem}.btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child)>.btn{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="radio"],.btn-group-toggle>.btn input[type="checkbox"],.btn-group-toggle>.btn-group>.btn input[type="radio"],.btn-group-toggle>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.custom-select,.input-group>.custom-file{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.form-control:focus,.input-group>.custom-select:focus,.input-group>.custom-file:focus{z-index:3}.input-group>.form-control+.form-control,.input-group>.form-control+.custom-select,.input-group>.form-control+.custom-file,.input-group>.custom-select+.form-control,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.custom-file,.input-group>.custom-file+.form-control,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.custom-file{margin-left:-1px}.input-group>.form-control:not(:last-child),.input-group>.custom-select:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.form-control:not(:first-child),.input-group>.custom-select:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::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-prepend,.input-group-append{display:-webkit-box;display:-ms-flexbox;display:flex}.input-group-prepend .btn,.input-group-append .btn{position:relative;z-index:2}.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.input-group-text,.input-group-append .input-group-text+.btn{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0.375rem 0.75rem;margin-bottom:0;font-size:0.875rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#F8F5F0;border:1px solid #ced4da;border-radius:0.25rem}.input-group-text input[type="radio"],.input-group-text input[type="checkbox"]{margin-top:0}.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text,.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.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){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:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.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){border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked ~ .custom-control-label::before{color:#fff;background-color:#325D88}.custom-control-input:focus ~ .custom-control-label::before{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(50,93,136,0.25);box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(50,93,136,0.25)}.custom-control-input:active ~ .custom-control-label::before{color:#fff;background-color:#95b6d8}.custom-control-input:disabled ~ .custom-control-label{color:#8E8C84}.custom-control-input:disabled ~ .custom-control-label::before{background-color:#F8F5F0}.custom-control-label{position:relative;margin-bottom:0}.custom-control-label::before{position:absolute;top:0.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#DFD7CA}.custom-control-label::after{position:absolute;top:0.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background-repeat:no-repeat;background-position:center center;background-size:50% 50%}.custom-checkbox .custom-control-label::before{border-radius:0.25rem}.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before{background-color:#325D88}.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before{background-color:#325D88}.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before{background-color:rgba(50,93,136,0.5)}.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before{background-color:rgba(50,93,136,0.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked ~ .custom-control-label::before{background-color:#325D88}.custom-radio .custom-control-input:checked ~ .custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before{background-color:rgba(50,93,136,0.5)}.custom-select{display:inline-block;width:100%;height:calc(2.0625rem + 2px);padding:0.375rem 1.75rem 0.375rem 0.75rem;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%233E3F3A' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center;background-size:8px 10px;border:1px solid #ced4da;border-radius:0.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#6f9dca;outline:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.075),0 0 5px rgba(111,157,202,0.5);box-shadow:inset 0 1px 2px rgba(0,0,0,0.075),0 0 5px rgba(111,157,202,0.5)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:0.75rem;background-image:none}.custom-select:disabled{color:#8E8C84;background-color:#F8F5F0}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:calc(1.6484375rem + 2px);padding-top:0.375rem;padding-bottom:0.375rem;font-size:75%}.custom-select-lg{height:calc(2.640625rem + 2px);padding-top:0.375rem;padding-bottom:0.375rem;font-size:125%}.custom-file{position:relative;display:inline-block;width:100%;height:calc(2.0625rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(2.0625rem + 2px);margin:0;opacity:0}.custom-file-input:focus ~ .custom-file-label{border-color:#6f9dca;-webkit-box-shadow:0 0 0 0.2rem rgba(50,93,136,0.25);box-shadow:0 0 0 0.2rem rgba(50,93,136,0.25)}.custom-file-input:focus ~ .custom-file-label::after{border-color:#6f9dca}.custom-file-input:lang(en) ~ .custom-file-label::after{content:"Browse"}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(2.0625rem + 2px);padding:0.375rem 0.75rem;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:0.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:2.0625rem;padding:0.375rem 0.75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#F8F5F0;border-left:1px solid #ced4da;border-radius:0 0.25rem 0.25rem 0}.custom-range{width:100%;padding-left:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:none}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-0.25rem;background-color:#325D88;border:0;border-radius:1rem;-webkit-appearance:none;appearance:none}.custom-range::-webkit-slider-thumb:focus{outline:none;-webkit-box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(50,93,136,0.25);box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(50,93,136,0.25)}.custom-range::-webkit-slider-thumb:active{background-color:#95b6d8}.custom-range::-webkit-slider-runnable-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:#DFD7CA;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#325D88;border:0;border-radius:1rem;-moz-appearance:none;appearance:none}.custom-range::-moz-range-thumb:focus{outline:none;box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(50,93,136,0.25)}.custom-range::-moz-range-thumb:active{background-color:#95b6d8}.custom-range::-moz-range-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:#DFD7CA;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;background-color:#325D88;border:0;border-radius:1rem;appearance:none}.custom-range::-ms-thumb:focus{outline:none;box-shadow:0 0 0 1px #fff,0 0 0 0.2rem rgba(50,93,136,0.25)}.custom-range::-ms-thumb:active{background-color:#95b6d8}.custom-range::-ms-track{width:100%;height:0.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:0.5rem}.custom-range::-ms-fill-lower{background-color:#DFD7CA;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#DFD7CA;border-radius:1rem}.nav{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:0.5rem 0.9rem}.nav-link:hover,.nav-link:focus{text-decoration:none}.nav-link.disabled{color:#DFD7CA}.nav-tabs{border-bottom:1px solid #DFD7CA}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:0.25rem;border-top-right-radius:0.25rem}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#DFD7CA}.nav-tabs .nav-link.disabled{color:#DFD7CA;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#495057;background-color:#fff;border-color:#DFD7CA #DFD7CA #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:0.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#8E8C84;background-color:#F8F5F0}.nav-fill .nav-item{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:0.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:0.3359375rem;padding-bottom:0.3359375rem;margin-right:1rem;font-size:1.09375rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:0.5rem;padding-bottom:0.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:0.25rem 0.75rem;font-size:1.09375rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:0.25rem}.navbar-toggler:hover,.navbar-toggler:focus{text-decoration:none}.navbar-toggler:not(:disabled):not(.disabled){cursor:pointer}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width: 575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width: 576px){.navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width: 767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width: 768px){.navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width: 991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width: 992px){.navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width: 1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width: 1200px){.navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:0.5rem;padding-left:0.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:#000}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:#000}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,0.5)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:#000}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,0.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.active{color:#000}.navbar-light .navbar-toggler{color:rgba(0,0,0,0.5);border-color:rgba(0,0,0,0.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,0.5)}.navbar-light .navbar-text a{color:#000}.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:#000}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,0.5)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:#fff}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,0.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,0.5);border-color:rgba(255,255,255,0.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:rgba(255,255,255,0.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.card{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(223,215,202,0.75);border-radius:0.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:0.25rem;border-top-right-radius:0.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:0.25rem;border-bottom-left-radius:0.25rem}.card-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:0.75rem}.card-subtitle{margin-top:-0.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:0.75rem 1.25rem;margin-bottom:0;background-color:rgba(248,245,240,0.25);border-bottom:1px solid rgba(223,215,202,0.75)}.card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:0.75rem 1.25rem;background-color:rgba(248,245,240,0.25);border-top:1px solid rgba(223,215,202,0.75)}.card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.card-header-tabs{margin-right:-0.625rem;margin-bottom:-0.75rem;margin-left:-0.625rem;border-bottom:0}.card-header-pills{margin-right:-0.625rem;margin-left:-0.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:calc(0.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(0.25rem - 1px);border-bottom-left-radius:calc(0.25rem - 1px)}.card-deck{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width: 576px){.card-deck{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width: 576px){.card-group{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:first-child .card-img-top,.card-group>.card:first-child .card-header{border-top-right-radius:0}.card-group>.card:first-child .card-img-bottom,.card-group>.card:first-child .card-footer{border-bottom-right-radius:0}.card-group>.card:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:last-child .card-img-top,.card-group>.card:last-child .card-header{border-top-left-radius:0}.card-group>.card:last-child .card-img-bottom,.card-group>.card:last-child .card-footer{border-bottom-left-radius:0}.card-group>.card:only-child{border-radius:0.25rem}.card-group>.card:only-child .card-img-top,.card-group>.card:only-child .card-header{border-top-left-radius:0.25rem;border-top-right-radius:0.25rem}.card-group>.card:only-child .card-img-bottom,.card-group>.card:only-child .card-footer{border-bottom-right-radius:0.25rem;border-bottom-left-radius:0.25rem}.card-group>.card:not(:first-child):not(:last-child):not(:only-child){border-radius:0}.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer{border-radius:0}}.card-columns .card{margin-bottom:0.75rem}@media (min-width: 576px){.card-columns{-webkit-column-count:3;column-count:3;-webkit-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion .card:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion .card:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion .card:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion .card:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.breadcrumb{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#F8F5F0;border-radius:0.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:0.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:0.5rem;color:#8E8C84;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#8E8C84}.pagination{display:-webkit-box;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:0.25rem}.page-link{position:relative;display:block;padding:0.5rem 0.75rem;margin-left:-1px;line-height:1.25;color:#8E8C84;background-color:#F8F5F0;border:1px solid #DFD7CA}.page-link:hover{z-index:2;color:#8E8C84;text-decoration:none;background-color:#F8F5F0;border-color:#DFD7CA}.page-link:focus{z-index:2;outline:0;-webkit-box-shadow:0 0 0 0.2rem rgba(50,93,136,0.25);box-shadow:0 0 0 0.2rem rgba(50,93,136,0.25)}.page-link:not(:disabled):not(.disabled){cursor:pointer}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:0.25rem;border-bottom-left-radius:0.25rem}.page-item:last-child .page-link{border-top-right-radius:0.25rem;border-bottom-right-radius:0.25rem}.page-item.active .page-link{z-index:1;color:#8E8C84;background-color:#DFD7CA;border-color:#DFD7CA}.page-item.disabled .page-link{color:#DFD7CA;pointer-events:none;cursor:auto;background-color:#F8F5F0;border-color:#DFD7CA}.pagination-lg .page-link{padding:0.75rem 1.5rem;font-size:1.09375rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:0.3rem;border-bottom-left-radius:0.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:0.3rem;border-bottom-right-radius:0.3rem}.pagination-sm .page-link{padding:0.25rem 0.5rem;font-size:0.765625rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:0.2rem;border-bottom-left-radius:0.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:0.2rem;border-bottom-right-radius:0.2rem}.badge{display:inline-block;padding:0.25em 0.4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:0.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:0.6em;padding-left:0.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#325D88}.badge-primary[href]:hover,.badge-primary[href]:focus{color:#fff;text-decoration:none;background-color:#244463}.badge-secondary{color:#fff;background-color:#8E8C84}.badge-secondary[href]:hover,.badge-secondary[href]:focus{color:#fff;text-decoration:none;background-color:#74726b}.badge-success{color:#fff;background-color:#93C54B}.badge-success[href]:hover,.badge-success[href]:focus{color:#fff;text-decoration:none;background-color:#79a736}.badge-info{color:#fff;background-color:#29ABE0}.badge-info[href]:hover,.badge-info[href]:focus{color:#fff;text-decoration:none;background-color:#1b8dbb}.badge-warning{color:#fff;background-color:#F47C3C}.badge-warning[href]:hover,.badge-warning[href]:focus{color:#fff;text-decoration:none;background-color:#ef5c0e}.badge-danger{color:#fff;background-color:#d9534f}.badge-danger[href]:hover,.badge-danger[href]:focus{color:#fff;text-decoration:none;background-color:#c9302c}.badge-light{color:#212529;background-color:#F8F5F0}.badge-light[href]:hover,.badge-light[href]:focus{color:#212529;text-decoration:none;background-color:#e8decd}.badge-dark{color:#fff;background-color:#3E3F3A}.badge-dark[href]:hover,.badge-dark[href]:focus{color:#fff;text-decoration:none;background-color:#242422}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#F8F5F0;border-radius:0.3rem}@media (min-width: 576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:0.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:0.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:3.8125rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:0.75rem 1.25rem;color:inherit}.alert-primary{color:#1a3047;background-color:#d6dfe7;border-color:#c6d2de}.alert-primary hr{border-top-color:#b6c5d5}.alert-primary .alert-link{color:#0c1722}.alert-secondary{color:#4a4945;background-color:#e8e8e6;border-color:#dfdfdd}.alert-secondary hr{border-top-color:#d3d3d0}.alert-secondary .alert-link{color:#302f2c}.alert-success{color:#4c6627;background-color:#e9f3db;border-color:#e1efcd}.alert-success hr{border-top-color:#d5e9ba}.alert-success .alert-link{color:#314119}.alert-info{color:#155974;background-color:#d4eef9;border-color:#c3e7f6}.alert-info hr{border-top-color:#addef3}.alert-info .alert-link{color:#0d3849}.alert-warning{color:#7f401f;background-color:#fde5d8;border-color:#fcdac8}.alert-warning hr{border-top-color:#fbcab0}.alert-warning .alert-link{color:#562b15}.alert-danger{color:#712b29;background-color:#f7dddc;border-color:#f4cfce}.alert-danger hr{border-top-color:#efbbb9}.alert-danger .alert-link{color:#4c1d1b}.alert-light{color:#817f7d;background-color:#fefdfc;border-color:#fdfcfb}.alert-light hr{border-top-color:#f5efea}.alert-light .alert-link{color:#676664}.alert-dark{color:#20211e;background-color:#d8d9d8;border-color:#c9c9c8}.alert-dark hr{border-top-color:#bcbcbb}.alert-dark .alert-link{color:#060606}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:0.65625rem;background-color:#DFD7CA;border-radius:10px}.progress-bar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;color:#325D88;text-align:center;white-space:nowrap;background-color:#325D88;-webkit-transition:width 0.6s ease;transition:width 0.6s ease}@media screen and (prefers-reduced-motion: reduce){.progress-bar{-webkit-transition:none;transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-ms-flex:1;flex:1}.list-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#3E3F3A;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{color:#3E3F3A;text-decoration:none;background-color:#F8F5F0}.list-group-item-action:active{color:#3E3F3A;background-color:#DFD7CA}.list-group-item{position:relative;display:block;padding:0.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid #DFD7CA}.list-group-item:first-child{border-top-left-radius:0.25rem;border-top-right-radius:0.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:0.25rem;border-bottom-left-radius:0.25rem}.list-group-item:hover,.list-group-item:focus{z-index:1;text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#98978B;background-color:#fff}.list-group-item.active{z-index:2;color:#3E3F3A;background-color:#F8F5F0;border-color:#DFD7CA}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#1a3047;background-color:#c6d2de}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#1a3047;background-color:#b6c5d5}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#1a3047;border-color:#1a3047}.list-group-item-secondary{color:#4a4945;background-color:#dfdfdd}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#4a4945;background-color:#d3d3d0}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#4a4945;border-color:#4a4945}.list-group-item-success{color:#4c6627;background-color:#e1efcd}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#4c6627;background-color:#d5e9ba}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#4c6627;border-color:#4c6627}.list-group-item-info{color:#155974;background-color:#c3e7f6}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#155974;background-color:#addef3}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#155974;border-color:#155974}.list-group-item-warning{color:#7f401f;background-color:#fcdac8}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#7f401f;background-color:#fbcab0}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#7f401f;border-color:#7f401f}.list-group-item-danger{color:#712b29;background-color:#f4cfce}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#712b29;background-color:#efbbb9}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#712b29;border-color:#712b29}.list-group-item-light{color:#817f7d;background-color:#fdfcfb}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#817f7d;background-color:#f5efea}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#817f7d;border-color:#817f7d}.list-group-item-dark{color:#20211e;background-color:#c9c9c8}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#20211e;background-color:#bcbcbb}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#20211e;border-color:#20211e}.close{float:right;font-size:1.3125rem;font-weight:700;line-height:1;color:#000;text-shadow:none;opacity:.5}.close:hover,.close:focus{color:#000;text-decoration:none;opacity:.75}.close:not(:disabled):not(.disabled){cursor:pointer}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:0.5rem;pointer-events:none}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform 0.3s ease-out;transition:-webkit-transform 0.3s ease-out;transition:transform 0.3s ease-out;transition:transform 0.3s ease-out, -webkit-transform 0.3s ease-out;-webkit-transform:translate(0, -25%);transform:translate(0, -25%)}@media screen and (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{-webkit-transition:none;transition:none}}.modal.show .modal-dialog{-webkit-transform:translate(0, 0);transform:translate(0, 0)}.modal-dialog-centered{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;min-height:calc(100% - (0.5rem * 2))}.modal-content{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid #DFD7CA;border-radius:0.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:0.5}.modal-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:1rem;border-bottom:1px solid #DFD7CA;border-top-left-radius:0.3rem;border-top-right-radius:0.3rem}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #DFD7CA}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-centered{min-height:calc(100% - (1.75rem * 2))}.modal-sm{max-width:300px}}@media (min-width: 992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:"Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.765625rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:0.9}.tooltip .arrow{position:absolute;display:block;width:0.8rem;height:0.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^="top"]{padding:0.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^="top"] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^="top"] .arrow::before{top:0;border-width:0.4rem 0.4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^="right"]{padding:0 0.4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^="right"] .arrow{left:0;width:0.4rem;height:0.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^="right"] .arrow::before{right:0;border-width:0.4rem 0.4rem 0.4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^="bottom"]{padding:0.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^="bottom"] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^="bottom"] .arrow::before{bottom:0;border-width:0 0.4rem 0.4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^="left"]{padding:0 0.4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^="left"] .arrow{right:0;width:0.4rem;height:0.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^="left"] .arrow::before{left:0;border-width:0.4rem 0 0.4rem 0.4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:0.25rem 0.5rem;color:#fff;text-align:center;background-color:#000;border-radius:0.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:"Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.765625rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);border-radius:0.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:0.5rem;margin:0 0.3rem}.popover .arrow::before,.popover .arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-top,.bs-popover-auto[x-placement^="top"]{margin-bottom:0.5rem}.bs-popover-top .arrow,.bs-popover-auto[x-placement^="top"] .arrow{bottom:calc((0.5rem + 1px) * -1)}.bs-popover-top .arrow::before,.bs-popover-auto[x-placement^="top"] .arrow::before,.bs-popover-top .arrow::after,.bs-popover-auto[x-placement^="top"] .arrow::after{border-width:0.5rem 0.5rem 0}.bs-popover-top .arrow::before,.bs-popover-auto[x-placement^="top"] .arrow::before{bottom:0;border-top-color:rgba(0,0,0,0.25)}.bs-popover-top .arrow::after,.bs-popover-auto[x-placement^="top"] .arrow::after{bottom:1px;border-top-color:#fff}.bs-popover-right,.bs-popover-auto[x-placement^="right"]{margin-left:0.5rem}.bs-popover-right .arrow,.bs-popover-auto[x-placement^="right"] .arrow{left:calc((0.5rem + 1px) * -1);width:0.5rem;height:1rem;margin:0.3rem 0}.bs-popover-right .arrow::before,.bs-popover-auto[x-placement^="right"] .arrow::before,.bs-popover-right .arrow::after,.bs-popover-auto[x-placement^="right"] .arrow::after{border-width:0.5rem 0.5rem 0.5rem 0}.bs-popover-right .arrow::before,.bs-popover-auto[x-placement^="right"] .arrow::before{left:0;border-right-color:rgba(0,0,0,0.25)}.bs-popover-right .arrow::after,.bs-popover-auto[x-placement^="right"] .arrow::after{left:1px;border-right-color:#fff}.bs-popover-bottom,.bs-popover-auto[x-placement^="bottom"]{margin-top:0.5rem}.bs-popover-bottom .arrow,.bs-popover-auto[x-placement^="bottom"] .arrow{top:calc((0.5rem + 1px) * -1)}.bs-popover-bottom .arrow::before,.bs-popover-auto[x-placement^="bottom"] .arrow::before,.bs-popover-bottom .arrow::after,.bs-popover-auto[x-placement^="bottom"] .arrow::after{border-width:0 0.5rem 0.5rem 0.5rem}.bs-popover-bottom .arrow::before,.bs-popover-auto[x-placement^="bottom"] .arrow::before{top:0;border-bottom-color:rgba(0,0,0,0.25)}.bs-popover-bottom .arrow::after,.bs-popover-auto[x-placement^="bottom"] .arrow::after{top:1px;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[x-placement^="bottom"] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-0.5rem;content:"";border-bottom:1px solid #F8F5F0}.bs-popover-left,.bs-popover-auto[x-placement^="left"]{margin-right:0.5rem}.bs-popover-left .arrow,.bs-popover-auto[x-placement^="left"] .arrow{right:calc((0.5rem + 1px) * -1);width:0.5rem;height:1rem;margin:0.3rem 0}.bs-popover-left .arrow::before,.bs-popover-auto[x-placement^="left"] .arrow::before,.bs-popover-left .arrow::after,.bs-popover-auto[x-placement^="left"] .arrow::after{border-width:0.5rem 0 0.5rem 0.5rem}.bs-popover-left .arrow::before,.bs-popover-auto[x-placement^="left"] .arrow::before{right:0;border-left-color:rgba(0,0,0,0.25)}.bs-popover-left .arrow::after,.bs-popover-auto[x-placement^="left"] .arrow::after{right:1px;border-left-color:#fff}.popover-header{padding:0.5rem 0.75rem;margin-bottom:0;font-size:0.875rem;color:inherit;background-color:#F8F5F0;border-bottom:1px solid #f0e9df;border-top-left-radius:calc(0.3rem - 1px);border-top-right-radius:calc(0.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:0.5rem 0.75rem;color:#3E3F3A}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%;-webkit-transition:-webkit-transform 0.6s ease;transition:-webkit-transform 0.6s ease;transition:transform 0.6s ease;transition:transform 0.6s ease, -webkit-transform 0.6s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}@media screen and (prefers-reduced-motion: reduce){.carousel-item{-webkit-transition:none;transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);transform:translateX(0)}@supports (-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}}.carousel-item-next,.active.carousel-item-right{-webkit-transform:translateX(100%);transform:translateX(100%)}@supports (-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d){.carousel-item-next,.active.carousel-item-right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0)}}.carousel-item-prev,.active.carousel-item-left{-webkit-transform:translateX(-100%);transform:translateX(-100%)}@supports (-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d){.carousel-item-prev,.active.carousel-item-left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0)}}.carousel-fade .carousel-item{opacity:0;-webkit-transition-duration:.6s;transition-duration:.6s;-webkit-transition-property:opacity;transition-property:opacity}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right{opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0}.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active,.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev{-webkit-transform:translateX(0);transform:translateX(0)}@supports (-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d){.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active,.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0)}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:0.5}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat center center;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:rgba(255,255,255,0.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.bg-primary{background-color:#325D88 !important}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#244463 !important}.bg-secondary{background-color:#8E8C84 !important}a.bg-secondary:hover,a.bg-secondary:focus,button.bg-secondary:hover,button.bg-secondary:focus{background-color:#74726b !important}.bg-success{background-color:#93C54B !important}a.bg-success:hover,a.bg-success:focus,button.bg-success:hover,button.bg-success:focus{background-color:#79a736 !important}.bg-info{background-color:#29ABE0 !important}a.bg-info:hover,a.bg-info:focus,button.bg-info:hover,button.bg-info:focus{background-color:#1b8dbb !important}.bg-warning{background-color:#F47C3C !important}a.bg-warning:hover,a.bg-warning:focus,button.bg-warning:hover,button.bg-warning:focus{background-color:#ef5c0e !important}.bg-danger{background-color:#d9534f !important}a.bg-danger:hover,a.bg-danger:focus,button.bg-danger:hover,button.bg-danger:focus{background-color:#c9302c !important}.bg-light{background-color:#F8F5F0 !important}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#e8decd !important}.bg-dark{background-color:#3E3F3A !important}a.bg-dark:hover,a.bg-dark:focus,button.bg-dark:hover,button.bg-dark:focus{background-color:#242422 !important}.bg-white{background-color:#fff !important}.bg-transparent{background-color:transparent !important}.border{border:1px solid #DFD7CA !important}.border-top{border-top:1px solid #DFD7CA !important}.border-right{border-right:1px solid #DFD7CA !important}.border-bottom{border-bottom:1px solid #DFD7CA !important}.border-left{border-left:1px solid #DFD7CA !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:#325D88 !important}.border-secondary{border-color:#8E8C84 !important}.border-success{border-color:#93C54B !important}.border-info{border-color:#29ABE0 !important}.border-warning{border-color:#F47C3C !important}.border-danger{border-color:#d9534f !important}.border-light{border-color:#F8F5F0 !important}.border-dark{border-color:#3E3F3A !important}.border-white{border-color:#fff !important}.rounded{border-radius:0.25rem !important}.rounded-top{border-top-left-radius:0.25rem !important;border-top-right-radius:0.25rem !important}.rounded-right{border-top-right-radius:0.25rem !important;border-bottom-right-radius:0.25rem !important}.rounded-bottom{border-bottom-right-radius:0.25rem !important;border-bottom-left-radius:0.25rem !important}.rounded-left{border-top-left-radius:0.25rem !important;border-bottom-left-radius:0.25rem !important}.rounded-circle{border-radius:50% !important}.rounded-0{border-radius:0 !important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}@media (min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-sm-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-md-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-lg-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-xl-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-print-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.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.8571428571%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-grow-1{-webkit-box-flex:1 !important;-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{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}@media (min-width: 576px){.flex-sm-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-sm-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-sm-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-sm-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-sm-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-sm-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-sm-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-sm-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-sm-grow-1{-webkit-box-flex:1 !important;-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{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-sm-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-sm-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-sm-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-sm-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-sm-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-sm-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-sm-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-sm-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-sm-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-sm-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-sm-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-sm-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-sm-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-sm-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-sm-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-sm-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-sm-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-sm-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-sm-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-sm-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-sm-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 768px){.flex-md-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-md-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-md-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-md-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-md-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-md-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-md-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-md-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-md-grow-1{-webkit-box-flex:1 !important;-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{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-md-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-md-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-md-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-md-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-md-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-md-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-md-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-md-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-md-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-md-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-md-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-md-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-md-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-md-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-md-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-md-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-md-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-md-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-md-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-md-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-md-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 992px){.flex-lg-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-lg-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-lg-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-lg-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-lg-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-lg-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-lg-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-lg-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-lg-grow-1{-webkit-box-flex:1 !important;-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{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-lg-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-lg-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-lg-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-lg-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-lg-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-lg-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-lg-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-lg-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-lg-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-lg-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-lg-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-lg-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-lg-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-lg-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-lg-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-lg-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-lg-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-lg-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-lg-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-lg-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-lg-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 1200px){.flex-xl-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-xl-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-xl-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-xl-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-xl-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-xl-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-xl-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-xl-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-xl-grow-1{-webkit-box-flex:1 !important;-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{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-xl-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-xl-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-xl-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-xl-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-xl-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-xl-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-xl-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-xl-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-xl-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-xl-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-xl-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-xl-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-xl-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-xl-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-xl-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-xl-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-xl-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-xl-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-xl-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-xl-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-xl-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}.float-left{float:left !important}.float-right{float:right !important}.float-none{float:none !important}@media (min-width: 576px){.float-sm-left{float:left !important}.float-sm-right{float:right !important}.float-sm-none{float:none !important}}@media (min-width: 768px){.float-md-left{float:left !important}.float-md-right{float:right !important}.float-md-none{float:none !important}}@media (min-width: 992px){.float-lg-left{float:left !important}.float-lg-right{float:right !important}.float-lg-none{float:none !important}}@media (min-width: 1200px){.float-xl-left{float:left !important}.float-xl-right{float:right !important}.float-xl-none{float:none !important}}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:-webkit-sticky !important;position:sticky !important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports (position: -webkit-sticky) or (position: sticky){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;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{-webkit-box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important;box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important}.shadow{-webkit-box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important;box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important}.shadow-lg{-webkit-box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important;box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important}.shadow-none{-webkit-box-shadow:none !important;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}.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:0.25rem !important}.mt-1,.my-1{margin-top:0.25rem !important}.mr-1,.mx-1{margin-right:0.25rem !important}.mb-1,.my-1{margin-bottom:0.25rem !important}.ml-1,.mx-1{margin-left:0.25rem !important}.m-2{margin:0.5rem !important}.mt-2,.my-2{margin-top:0.5rem !important}.mr-2,.mx-2{margin-right:0.5rem !important}.mb-2,.my-2{margin-bottom:0.5rem !important}.ml-2,.mx-2{margin-left:0.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:0.25rem !important}.pt-1,.py-1{padding-top:0.25rem !important}.pr-1,.px-1{padding-right:0.25rem !important}.pb-1,.py-1{padding-bottom:0.25rem !important}.pl-1,.px-1{padding-left:0.25rem !important}.p-2{padding:0.5rem !important}.pt-2,.py-2{padding-top:0.5rem !important}.pr-2,.px-2{padding-right:0.5rem !important}.pb-2,.py-2{padding-bottom:0.5rem !important}.pl-2,.px-2{padding-left:0.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media (min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:0.25rem !important}.mt-sm-1,.my-sm-1{margin-top:0.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:0.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:0.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:0.25rem !important}.m-sm-2{margin:0.5rem !important}.mt-sm-2,.my-sm-2{margin-top:0.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:0.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:0.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:0.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:0.25rem !important}.pt-sm-1,.py-sm-1{padding-top:0.25rem !important}.pr-sm-1,.px-sm-1{padding-right:0.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:0.25rem !important}.pl-sm-1,.px-sm-1{padding-left:0.25rem !important}.p-sm-2{padding:0.5rem !important}.pt-sm-2,.py-sm-2{padding-top:0.5rem !important}.pr-sm-2,.px-sm-2{padding-right:0.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:0.5rem !important}.pl-sm-2,.px-sm-2{padding-left:0.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:0.25rem !important}.mt-md-1,.my-md-1{margin-top:0.25rem !important}.mr-md-1,.mx-md-1{margin-right:0.25rem !important}.mb-md-1,.my-md-1{margin-bottom:0.25rem !important}.ml-md-1,.mx-md-1{margin-left:0.25rem !important}.m-md-2{margin:0.5rem !important}.mt-md-2,.my-md-2{margin-top:0.5rem !important}.mr-md-2,.mx-md-2{margin-right:0.5rem !important}.mb-md-2,.my-md-2{margin-bottom:0.5rem !important}.ml-md-2,.mx-md-2{margin-left:0.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:0.25rem !important}.pt-md-1,.py-md-1{padding-top:0.25rem !important}.pr-md-1,.px-md-1{padding-right:0.25rem !important}.pb-md-1,.py-md-1{padding-bottom:0.25rem !important}.pl-md-1,.px-md-1{padding-left:0.25rem !important}.p-md-2{padding:0.5rem !important}.pt-md-2,.py-md-2{padding-top:0.5rem !important}.pr-md-2,.px-md-2{padding-right:0.5rem !important}.pb-md-2,.py-md-2{padding-bottom:0.5rem !important}.pl-md-2,.px-md-2{padding-left:0.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media (min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:0.25rem !important}.mt-lg-1,.my-lg-1{margin-top:0.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:0.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:0.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:0.25rem !important}.m-lg-2{margin:0.5rem !important}.mt-lg-2,.my-lg-2{margin-top:0.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:0.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:0.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:0.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:0.25rem !important}.pt-lg-1,.py-lg-1{padding-top:0.25rem !important}.pr-lg-1,.px-lg-1{padding-right:0.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:0.25rem !important}.pl-lg-1,.px-lg-1{padding-left:0.25rem !important}.p-lg-2{padding:0.5rem !important}.pt-lg-2,.py-lg-2{padding-top:0.5rem !important}.pr-lg-2,.px-lg-2{padding-right:0.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:0.5rem !important}.pl-lg-2,.px-lg-2{padding-left:0.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media (min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:0.25rem !important}.mt-xl-1,.my-xl-1{margin-top:0.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:0.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:0.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:0.25rem !important}.m-xl-2{margin:0.5rem !important}.mt-xl-2,.my-xl-2{margin-top:0.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:0.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:0.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:0.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:0.25rem !important}.pt-xl-1,.py-xl-1{padding-top:0.25rem !important}.pr-xl-1,.px-xl-1{padding-right:0.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:0.25rem !important}.pl-xl-1,.px-xl-1{padding-left:0.25rem !important}.p-xl-2{padding:0.5rem !important}.pt-xl-2,.py-xl-2{padding-top:0.5rem !important}.pr-xl-2,.px-xl-2{padding-right:0.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:0.5rem !important}.pl-xl-2,.px-xl-2{padding-left:0.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.text-monospace{font-family:SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}.text-justify{text-align:justify !important}.text-nowrap{white-space:nowrap !important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}@media (min-width: 576px){.text-sm-left{text-align:left !important}.text-sm-right{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.text-md-left{text-align:left !important}.text-md-right{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.text-lg-left{text-align:left !important}.text-lg-right{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.text-xl-left{text-align:left !important}.text-xl-right{text-align:right !important}.text-xl-center{text-align:center !important}}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.font-weight-light{font-weight:300 !important}.font-weight-normal{font-weight:400 !important}.font-weight-bold{font-weight:700 !important}.font-italic{font-style:italic !important}.text-white{color:#fff !important}.text-primary{color:#325D88 !important}a.text-primary:hover,a.text-primary:focus{color:#244463 !important}.text-secondary{color:#8E8C84 !important}a.text-secondary:hover,a.text-secondary:focus{color:#74726b !important}.text-success{color:#93C54B !important}a.text-success:hover,a.text-success:focus{color:#79a736 !important}.text-info{color:#29ABE0 !important}a.text-info:hover,a.text-info:focus{color:#1b8dbb !important}.text-warning{color:#F47C3C !important}a.text-warning:hover,a.text-warning:focus{color:#ef5c0e !important}.text-danger{color:#d9534f !important}a.text-danger:hover,a.text-danger:focus{color:#c9302c !important}.text-light{color:#F8F5F0 !important}a.text-light:hover,a.text-light:focus{color:#e8decd !important}.text-dark{color:#3E3F3A !important}a.text-dark:hover,a.text-dark:focus{color:#242422 !important}.text-body{color:#3E3F3A !important}.text-muted{color:#8E8C84 !important}.text-black-50{color:rgba(0,0,0,0.5) !important}.text-white-50{color:rgba(255,255,255,0.5) !important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media print{*,*::before,*::after{text-shadow:none !important;-webkit-box-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}pre,blockquote{border:1px solid #98978B;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}p,h2,h3{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 th,.table-bordered td{border:1px solid #DFD7CA !important}.table-dark{color:inherit}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#DFD7CA}.table .thead-dark th{color:inherit;border-color:#DFD7CA}}.bg-primary{background-color:#3E3F3A !important}.bg-dark{background-color:#8E8C84 !important}.bg-light{background-color:#F8F5F0 !important}.sandstone,.navbar .nav-link,.btn,.nav-tabs .nav-link,.nav-pills .nav-link,.breadcrumb,.pagination,.dropdown-menu .dropdown-item,.tooltip{font-size:11px;line-height:22px;font-weight:500;text-transform:uppercase}.navbar-form input,.navbar-form .form-control{border:none}.btn:hover{border-color:transparent}.btn-success,.btn-warning{color:#fff}.table .thead-dark th{background-color:#3E3F3A}.nav-tabs .nav-link{background-color:#F8F5F0;border-color:#DFD7CA}.nav-tabs .nav-link,.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{color:#8E8C84}.nav-tabs .nav-link.disabled,.nav-tabs .nav-link.disabled:hover,.nav-tabs .nav-link.disabled:focus{background-color:#F8F5F0;border-color:#DFD7CA;color:#DFD7CA}.nav-pills .nav-link{border:1px solid transparent;color:#8E8C84}.nav-pills .nav-link.active,.nav-pills .nav-link:hover,.nav-pills .nav-link:focus{background-color:#F8F5F0;border-color:#DFD7CA}.nav-pills .nav-link.disabled,.nav-pills .nav-link.disabled:hover{background-color:transparent;border-color:transparent;color:#DFD7CA}.breadcrumb{border:1px solid #DFD7CA}.pagination a:hover{text-decoration:none}.alert{color:#fff}.alert a,.alert .alert-link{color:#fff;text-decoration:underline}.alert-primary,.alert-primary>th,.alert-primary>td{background-color:#325D88}.alert-secondary,.alert-secondary>th,.alert-secondary>td{background-color:#8E8C84}.alert-success,.alert-success>th,.alert-success>td{background-color:#93C54B}.alert-info,.alert-info>th,.alert-info>td{background-color:#29ABE0}.alert-danger,.alert-danger>th,.alert-danger>td{background-color:#d9534f}.alert-warning,.alert-warning>th,.alert-warning>td{background-color:#F47C3C}.alert-dark,.alert-dark>th,.alert-dark>td{background-color:#3E3F3A}.alert-light,.alert-light>th,.alert-light>td{background-color:#F8F5F0}.alert-light,.alert-light a:not(.btn),.alert-light .alert-link{color:#3E3F3A}.badge-success,.badge-warning{color:#fff}.close{color:#DFD7CA;opacity:1}.close:hover{color:#b9a78a} \ No newline at end of file diff --git a/blogContent/projects/steam/error.html b/blogContent/projects/steam/error.html new file mode 100644 index 0000000..cefe1e1 --- /dev/null +++ b/blogContent/projects/steam/error.html @@ -0,0 +1,143 @@ + + +
+ +Sorry about that, you should try again some other day.
+ +
+ Option 1:
+ If you have steam open, simply click on the profile which you would like to view
+ from your friends list. The steam ID will be in the url that appears in the steam
+ browser.
+
+
+ Option 2:
+ If you only know the steam username, you can use steam ID look up sites like
+ STEAMID I/O. For this website, you will want
+ to use the steamID64 number.
+
+
Great question, I will get back to you on that one.
+Contrary to popular belief, Java is not a terrible language. For this project + I needed something that was easy to work with a Gremlin database -- the tinkerpop framework makes + this very convenient. Overall, I needed a backend because I cannot dish out my steam api key to users. + Plus, this way I can cache steam friends making graph creation times faster.
+ + +Yes. You can read all about Steam's API usage here.
+Go for it, all the code is on GitHub. I am going to be making a "comprehensive" docs which + should explain how to run this.
+Since the server caches all the friend requests in a local graph database, it is possible to + not see all your friends if you recently added them. I am working on a solution to this, + however, I don't want to excessively hammer the steam API if I don't have to.
+Using the form on this page, you enter your steamID and select the + graph type you wish to use and then press generate. This will take you to a + new page where your graph will render. Rendering will take between 1-4 minutes depending + on how many friends you have on your graph. Once all the friends are on the graph, it will + shake bringing it to its "final form".
+
+ Every steam user has an unique ID. This is NOT your username.
+ If you have steam open, simply click on the profile which you would like to view
+ from your friends list. The steam ID will be in the url that appears in the steam
+ browser.
+
+
+
+ This graph will display all of your friends in addition to all of their friends.
+
ex:
+
+
+ This graph will only display your friends, however, it will draw edges between your friends
+ if they are friends with each other.
+
ex:
+
+
This is a project that I threw together during a weekend to play around with + graph databases. This project uses the steam api to acquire people's friends lists; + this information is stored locally in a gremlin database. The client is sent information to + render on their javascript graph as it is pulled from the graph database via a web socket. +
+If you are interested in this project, or want to help work on it, check it out + on github.
+'+q+"
",h.numbers&&(q='
')).appendTo(repo);
+ if(typeof _this.extensions[extension] != 'undefined')
+ el.find('code').addClass(_this.extensions[extension]);
+ el.find('code').html(String(decode64(response.data.content)).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'));
+ el.find('pre').vanGogh();
+ }
+
+ transition(el, 'left');
+ },
+ error: function(response){
+ if(console && console.log)
+ console.log('Request Error:', e);
+ }
+ });
+ }
+
+ // Is link a folder
+ } else if(parent.hasClass('dir')) {
+
+ _this.container
+ .find('h1')
+ .find('.active')
+ .removeClass('active')
+ .end()
+ .append('' + link.text() + '');
+ transition(el, 'left');
+
+ // Is link a back link
+ } else if(parent.hasClass('back')){
+
+ _this.container.find('h1 a').last().remove();
+ el = page[0].id.split('_split_').slice(0,-1).join('_split_');
+ el = (el == _this.namespace) ? _this.container.find('.page').first() : $('#' + el);
+ transition(el, 'right');
+
+ // Is nav link
+ } else {
+ el = el.length ? el : _this.container.find('.page').eq(link.index());
+
+ if(link[0] !== _this.container.find('h1 a')[0])
+ link.addClass('active');
+ _this.container.find('h1 a').slice((link.index()+1),_this.container.find('h1 a').length).remove();
+ transition(el, 'right');
+ }
+ });
+ },
+ error : function(response){
+ if(console && console.log)
+ console.log('Request Error:', response);
+ }
+ });
+
+ // Setup repo container
+ return this.each(function(){
+ _this.container = $('').appendTo($(this));
+ });
+ };
+
+})(jQuery);
+
diff --git a/blogContent/projects/steam/src/RepoJS/repo.min.js b/blogContent/projects/steam/src/RepoJS/repo.min.js
new file mode 100644
index 0000000..5a3beb9
--- /dev/null
+++ b/blogContent/projects/steam/src/RepoJS/repo.min.js
@@ -0,0 +1,29 @@
+/*!
+ * @mekwall's .vangogh() for Syntax Highlighting
+ *
+ * All code is open source and dual licensed under GPL and MIT.
+ * Check the individual licenses for more information.
+ * https://github.com/mekwall/jquery-vangogh/blob/master/GPL-LICENSE.txt
+ * https://github.com/mekwall/jquery-vangogh/blob/master/MIT-LICENSE.txt
+ */
+(function($,a,b){var c=1,d=!1,e=!1,f={get:function(b){var c=a.location.hash;if(c.length>0){var d=c.match(new RegExp(b+":{([a-zA-Z0-9,-]*)}"));if(d)return d[1].split(",")}return[]},set:function(b,c){var d=a.location.hash,e,f=b+":{"+c.join(",")+"}",g=d.indexOf(b+":{");if(c.length===0)return this.remove(b);g!==-1?e=d.replace(new RegExp("("+b+":{[a-zA-Z0-9,-]*})"),f):e=d.length>0?d+","+f:f,a.location.hash=e},remove:function(b){a.location.hash=a.location.hash.replace(new RegExp("([,]?"+b+":{[a-zA-Z0-9,-]*}[,]?)"),"")}},g={numberRange:/^([0-9]+)-([0-9]+)$/,pageNumber:/-([0-9]+)$/,multilineBegin:/(?:.[^<]*(?!<\/span>)|)$/ig,multilineEnd:/()?(?:.[^<]*)?(<\/span>)/ig};$.fn.vanGogh=function(h){function n(){if(d||e)setTimeout(n,100);else{k++;if(k>=10)return;if(h.source&&!l){e=!0,$.ajax({url:h.source,crossDomain:!0,dataType:"text",success:function(a){l=a},error:function(a,b){l="ERROR: "+b},complete:function(){e=!1,n()}});return}b=b||a.hljs;if(!b){d=!0,$.getScript(h.autoload,function(){d=!1,n()});return}j.filter("pre,code").each(function(){function r(b,c,e){var h=!1,i=a.find(".vg-line");c&&(a.find(".vg-highlight").removeClass("vg-highlight"),f.remove(d),k=[]),b=$.type(b)==="array"?b:[b],$.each(b,function(b,c){if(k.indexOf(c)<=-1){!isNaN(parseFloat(c,10))&&isFinite(c)&&(c=parseInt(c,10));if($.type(c)==="string"){var e=g.numberRange.exec(c);if(e){var f=e[1],h=e[2],j="";for(var b=f;b<=h;b++)j+=",#"+d+"-"+b,k.push(b);i.filter(j.substring(1)).addClass("vg-highlight")}else a.find(".vg-line:contains("+c+")").each(function(){var a=$(this).addClass("vg-highlight");a.html(a.html().replace(c,''+c+""))}),k.push(c)}else{var l=d+"-"+this,m=i.filter("#"+l);m.length&&(m.addClass("vg-highlight"),k.push(c))}}}),!e&&f.set(d,k)}var a=$(this).addClass("vg-container").attr("id",this.id||"vg-"+c++),d=this.id,e=a.find("code"),i=!1,j=!1,k=[];e.length||(e=a,i=!0),h.source&&l&&e.text(l);var n=e.text();b.highlightBlock(e[0],h.tab);var o=e.html().split("\n"),p="",q="";if(!i){var s={},t=0;$.each(o,function(a,b){var c=a+h.firstLine,e=d+"-"+c,f=b;h.numbers&&(p+=''+c+"");if(s[t]){var i=g.multilineEnd.exec(b);i&&!i[1]?(f=''+f,delete s[t],t--):f=''+f+""}var j=g.multilineBegin.exec(b);j&&(t++,s[t]=j[1]),q+=''+q+"
",h.numbers&&(q='
")).appendTo(m);if(typeof g.extensions[v]!="undefined"){n.find("code").addClass(g.extensions[v])}n.find("code").html(String(c(t.data.content)).replace(/&/g,"&").replace(//g,">").replace(/"/g,"""));n.find("pre").vanGogh()
+}h(n,"left")},error:function(s){if(console&&console.log){console.log("Request Error:",r)}}})}}else{if(o.hasClass("dir")){g.container.find("h1").find(".active").removeClass("active").end().append(''+p.text()+"");h(n,"left")}else{if(o.hasClass("back")){g.container.find("h1 a").last().remove();n=q[0].id.split("_split_").slice(0,-1).join("_split_");n=(n==g.namespace)?g.container.find(".page").first():a("#"+n);h(n,"right")}else{n=n.length?n:g.container.find(".page").eq(p.index());
+if(p[0]!==g.container.find("h1 a")[0]){p.addClass("active")}g.container.find("h1 a").slice((p.index()+1),g.container.find("h1 a").length).remove();h(n,"right")}}}})},error:function(k){if(console&&console.log){console.log("Request Error:",k)}}});return this.each(function(){g.container=a('').appendTo(a(this))
+})}})(jQuery);
diff --git a/blogContent/projects/steam/src/captors/sigma.captors.mouse.js b/blogContent/projects/steam/src/captors/sigma.captors.mouse.js
new file mode 100644
index 0000000..e3a40c5
--- /dev/null
+++ b/blogContent/projects/steam/src/captors/sigma.captors.mouse.js
@@ -0,0 +1,349 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.captors');
+
+ /**
+ * The user inputs default captor. It deals with mouse events, keyboards
+ * events and touch events.
+ *
+ * @param {DOMElement} target The DOM element where the listeners will be
+ * bound.
+ * @param {camera} camera The camera related to the target.
+ * @param {configurable} settings The settings function.
+ * @return {sigma.captor} The fresh new captor instance.
+ */
+ sigma.captors.mouse = function(target, camera, settings) {
+ var _self = this,
+ _target = target,
+ _camera = camera,
+ _settings = settings,
+
+ // CAMERA MANAGEMENT:
+ // ******************
+ // The camera position when the user starts dragging:
+ _startCameraX,
+ _startCameraY,
+ _startCameraAngle,
+
+ // The latest stage position:
+ _lastCameraX,
+ _lastCameraY,
+ _lastCameraAngle,
+ _lastCameraRatio,
+
+ // MOUSE MANAGEMENT:
+ // *****************
+ // The mouse position when the user starts dragging:
+ _startMouseX,
+ _startMouseY,
+
+ _isMouseDown,
+ _isMoving,
+ _hasDragged,
+ _downStartTime,
+ _movingTimeoutId;
+
+ sigma.classes.dispatcher.extend(this);
+
+ sigma.utils.doubleClick(_target, 'click', _doubleClickHandler);
+ _target.addEventListener('DOMMouseScroll', _wheelHandler, false);
+ _target.addEventListener('mousewheel', _wheelHandler, false);
+ _target.addEventListener('mousemove', _moveHandler, false);
+ _target.addEventListener('mousedown', _downHandler, false);
+ _target.addEventListener('click', _clickHandler, false);
+ _target.addEventListener('mouseout', _outHandler, false);
+ document.addEventListener('mouseup', _upHandler, false);
+
+
+
+
+ /**
+ * This method unbinds every handlers that makes the captor work.
+ */
+ this.kill = function() {
+ sigma.utils.unbindDoubleClick(_target, 'click');
+ _target.removeEventListener('DOMMouseScroll', _wheelHandler);
+ _target.removeEventListener('mousewheel', _wheelHandler);
+ _target.removeEventListener('mousemove', _moveHandler);
+ _target.removeEventListener('mousedown', _downHandler);
+ _target.removeEventListener('click', _clickHandler);
+ _target.removeEventListener('mouseout', _outHandler);
+ document.removeEventListener('mouseup', _upHandler);
+ };
+
+
+
+
+ // MOUSE EVENTS:
+ // *************
+
+ /**
+ * The handler listening to the 'move' mouse event. It will effectively
+ * drag the graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _moveHandler(e) {
+ var x,
+ y,
+ pos;
+
+ // Dispatch event:
+ if (_settings('mouseEnabled')) {
+ _self.dispatchEvent('mousemove',
+ sigma.utils.mouseCoords(e));
+
+ if (_isMouseDown) {
+ _isMoving = true;
+ _hasDragged = true;
+
+ if (_movingTimeoutId)
+ clearTimeout(_movingTimeoutId);
+
+ _movingTimeoutId = setTimeout(function() {
+ _isMoving = false;
+ }, _settings('dragTimeout'));
+
+ sigma.misc.animation.killAll(_camera);
+
+ _camera.isMoving = true;
+ pos = _camera.cameraPosition(
+ sigma.utils.getX(e) - _startMouseX,
+ sigma.utils.getY(e) - _startMouseY,
+ true
+ );
+
+ x = _startCameraX - pos.x;
+ y = _startCameraY - pos.y;
+
+ if (x !== _camera.x || y !== _camera.y) {
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ _camera.goTo({
+ x: x,
+ y: y
+ });
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+ }
+ }
+
+ /**
+ * The handler listening to the 'up' mouse event. It will stop dragging the
+ * graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _upHandler(e) {
+ if (_settings('mouseEnabled') && _isMouseDown) {
+ _isMouseDown = false;
+ if (_movingTimeoutId)
+ clearTimeout(_movingTimeoutId);
+
+ _camera.isMoving = false;
+
+ var x = sigma.utils.getX(e),
+ y = sigma.utils.getY(e);
+
+ if (_isMoving) {
+ sigma.misc.animation.killAll(_camera);
+ sigma.misc.animation.camera(
+ _camera,
+ {
+ x: _camera.x +
+ _settings('mouseInertiaRatio') * (_camera.x - _lastCameraX),
+ y: _camera.y +
+ _settings('mouseInertiaRatio') * (_camera.y - _lastCameraY)
+ },
+ {
+ easing: 'quadraticOut',
+ duration: _settings('mouseInertiaDuration')
+ }
+ );
+ } else if (
+ _startMouseX !== x ||
+ _startMouseY !== y
+ )
+ _camera.goTo({
+ x: _camera.x,
+ y: _camera.y
+ });
+
+ _self.dispatchEvent('mouseup',
+ sigma.utils.mouseCoords(e));
+
+ // Update _isMoving flag:
+ _isMoving = false;
+ }
+ }
+
+ /**
+ * The handler listening to the 'down' mouse event. It will start observing
+ * the mouse position for dragging the graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _downHandler(e) {
+ if (_settings('mouseEnabled')) {
+ _startCameraX = _camera.x;
+ _startCameraY = _camera.y;
+
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ _startMouseX = sigma.utils.getX(e);
+ _startMouseY = sigma.utils.getY(e);
+
+ _hasDragged = false;
+ _downStartTime = (new Date()).getTime();
+
+ switch (e.which) {
+ case 2:
+ // Middle mouse button pressed
+ // Do nothing.
+ break;
+ case 3:
+ // Right mouse button pressed
+ _self.dispatchEvent('rightclick',
+ sigma.utils.mouseCoords(e, _startMouseX, _startMouseY));
+ break;
+ // case 1:
+ default:
+ // Left mouse button pressed
+ _isMouseDown = true;
+
+ _self.dispatchEvent('mousedown',
+ sigma.utils.mouseCoords(e, _startMouseX, _startMouseY));
+ }
+ }
+ }
+
+ /**
+ * The handler listening to the 'out' mouse event. It will just redispatch
+ * the event.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _outHandler(e) {
+ if (_settings('mouseEnabled'))
+ _self.dispatchEvent('mouseout');
+ }
+
+ /**
+ * The handler listening to the 'click' mouse event. It will redispatch the
+ * click event, but with normalized X and Y coordinates.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _clickHandler(e) {
+ if (_settings('mouseEnabled')) {
+ var event = sigma.utils.mouseCoords(e);
+ event.isDragging =
+ (((new Date()).getTime() - _downStartTime) > 100) && _hasDragged;
+ _self.dispatchEvent('click', event);
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+
+ /**
+ * The handler listening to the double click custom event. It will
+ * basically zoom into the graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _doubleClickHandler(e) {
+ var pos,
+ ratio,
+ animation;
+
+ if (_settings('mouseEnabled')) {
+ ratio = 1 / _settings('doubleClickZoomingRatio');
+
+ _self.dispatchEvent('doubleclick',
+ sigma.utils.mouseCoords(e, _startMouseX, _startMouseY));
+
+ if (_settings('doubleClickEnabled')) {
+ pos = _camera.cameraPosition(
+ sigma.utils.getX(e) - sigma.utils.getCenter(e).x,
+ sigma.utils.getY(e) - sigma.utils.getCenter(e).y,
+ true
+ );
+
+ animation = {
+ duration: _settings('doubleClickZoomDuration')
+ };
+
+ sigma.utils.zoomTo(_camera, pos.x, pos.y, ratio, animation);
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+ }
+
+ /**
+ * The handler listening to the 'wheel' mouse event. It will basically zoom
+ * in or not into the graph.
+ *
+ * @param {event} e A mouse event.
+ */
+ function _wheelHandler(e) {
+ var pos,
+ ratio,
+ animation,
+ wheelDelta = sigma.utils.getDelta(e);
+
+ if (_settings('mouseEnabled') && _settings('mouseWheelEnabled') && wheelDelta !== 0) {
+ ratio = wheelDelta > 0 ?
+ 1 / _settings('zoomingRatio') :
+ _settings('zoomingRatio');
+
+ pos = _camera.cameraPosition(
+ sigma.utils.getX(e) - sigma.utils.getCenter(e).x,
+ sigma.utils.getY(e) - sigma.utils.getCenter(e).y,
+ true
+ );
+
+ animation = {
+ duration: _settings('mouseZoomDuration')
+ };
+
+ sigma.utils.zoomTo(_camera, pos.x, pos.y, ratio, animation);
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+ }
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/captors/sigma.captors.touch.js b/blogContent/projects/steam/src/captors/sigma.captors.touch.js
new file mode 100644
index 0000000..0e4d987
--- /dev/null
+++ b/blogContent/projects/steam/src/captors/sigma.captors.touch.js
@@ -0,0 +1,410 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.captors');
+
+ /**
+ * The user inputs default captor. It deals with mouse events, keyboards
+ * events and touch events.
+ *
+ * @param {DOMElement} target The DOM element where the listeners will be
+ * bound.
+ * @param {camera} camera The camera related to the target.
+ * @param {configurable} settings The settings function.
+ * @return {sigma.captor} The fresh new captor instance.
+ */
+ sigma.captors.touch = function(target, camera, settings) {
+ var _self = this,
+ _target = target,
+ _camera = camera,
+ _settings = settings,
+
+ // CAMERA MANAGEMENT:
+ // ******************
+ // The camera position when the user starts dragging:
+ _startCameraX,
+ _startCameraY,
+ _startCameraAngle,
+ _startCameraRatio,
+
+ // The latest stage position:
+ _lastCameraX,
+ _lastCameraY,
+ _lastCameraAngle,
+ _lastCameraRatio,
+
+ // TOUCH MANAGEMENT:
+ // *****************
+ // Touches that are down:
+ _downTouches = [],
+
+ _startTouchX0,
+ _startTouchY0,
+ _startTouchX1,
+ _startTouchY1,
+ _startTouchAngle,
+ _startTouchDistance,
+
+ _touchMode,
+
+ _isMoving,
+ _doubleTap,
+ _movingTimeoutId;
+
+ sigma.classes.dispatcher.extend(this);
+
+ sigma.utils.doubleClick(_target, 'touchstart', _doubleTapHandler);
+ _target.addEventListener('touchstart', _handleStart, false);
+ _target.addEventListener('touchend', _handleLeave, false);
+ _target.addEventListener('touchcancel', _handleLeave, false);
+ _target.addEventListener('touchleave', _handleLeave, false);
+ _target.addEventListener('touchmove', _handleMove, false);
+
+ function position(e) {
+ var offset = sigma.utils.getOffset(_target);
+
+ return {
+ x: e.pageX - offset.left,
+ y: e.pageY - offset.top
+ };
+ }
+
+ /**
+ * This method unbinds every handlers that makes the captor work.
+ */
+ this.kill = function() {
+ sigma.utils.unbindDoubleClick(_target, 'touchstart');
+ _target.addEventListener('touchstart', _handleStart);
+ _target.addEventListener('touchend', _handleLeave);
+ _target.addEventListener('touchcancel', _handleLeave);
+ _target.addEventListener('touchleave', _handleLeave);
+ _target.addEventListener('touchmove', _handleMove);
+ };
+
+ // TOUCH EVENTS:
+ // *************
+ /**
+ * The handler listening to the 'touchstart' event. It will set the touch
+ * mode ("_touchMode") and start observing the user touch moves.
+ *
+ * @param {event} e A touch event.
+ */
+ function _handleStart(e) {
+ if (_settings('touchEnabled')) {
+ var x0,
+ x1,
+ y0,
+ y1,
+ pos0,
+ pos1;
+
+ _downTouches = e.touches;
+
+ switch (_downTouches.length) {
+ case 1:
+ _camera.isMoving = true;
+ _touchMode = 1;
+
+ _startCameraX = _camera.x;
+ _startCameraY = _camera.y;
+
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ pos0 = position(_downTouches[0]);
+ _startTouchX0 = pos0.x;
+ _startTouchY0 = pos0.y;
+
+ break;
+ case 2:
+ _camera.isMoving = true;
+ _touchMode = 2;
+
+ pos0 = position(_downTouches[0]);
+ pos1 = position(_downTouches[1]);
+ x0 = pos0.x;
+ y0 = pos0.y;
+ x1 = pos1.x;
+ y1 = pos1.y;
+
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ _startCameraAngle = _camera.angle;
+ _startCameraRatio = _camera.ratio;
+
+ _startCameraX = _camera.x;
+ _startCameraY = _camera.y;
+
+ _startTouchX0 = x0;
+ _startTouchY0 = y0;
+ _startTouchX1 = x1;
+ _startTouchY1 = y1;
+
+ _startTouchAngle = Math.atan2(
+ _startTouchY1 - _startTouchY0,
+ _startTouchX1 - _startTouchX0
+ );
+ _startTouchDistance = Math.sqrt(
+ (_startTouchY1 - _startTouchY0) *
+ (_startTouchY1 - _startTouchY0) +
+ (_startTouchX1 - _startTouchX0) *
+ (_startTouchX1 - _startTouchX0)
+ );
+
+ e.preventDefault();
+ return false;
+ }
+ }
+ }
+
+ /**
+ * The handler listening to the 'touchend', 'touchcancel' and 'touchleave'
+ * event. It will update the touch mode if there are still at least one
+ * finger, and stop dragging else.
+ *
+ * @param {event} e A touch event.
+ */
+ function _handleLeave(e) {
+ if (_settings('touchEnabled')) {
+ _downTouches = e.touches;
+ var inertiaRatio = _settings('touchInertiaRatio');
+
+ if (_movingTimeoutId) {
+ _isMoving = false;
+ clearTimeout(_movingTimeoutId);
+ }
+
+ switch (_touchMode) {
+ case 2:
+ if (e.touches.length === 1) {
+ _handleStart(e);
+
+ e.preventDefault();
+ break;
+ }
+ /* falls through */
+ case 1:
+ _camera.isMoving = false;
+ _self.dispatchEvent('stopDrag');
+
+ if (_isMoving) {
+ _doubleTap = false;
+ sigma.misc.animation.camera(
+ _camera,
+ {
+ x: _camera.x +
+ inertiaRatio * (_camera.x - _lastCameraX),
+ y: _camera.y +
+ inertiaRatio * (_camera.y - _lastCameraY)
+ },
+ {
+ easing: 'quadraticOut',
+ duration: _settings('touchInertiaDuration')
+ }
+ );
+ }
+
+ _isMoving = false;
+ _touchMode = 0;
+ break;
+ }
+ }
+ }
+
+ /**
+ * The handler listening to the 'touchmove' event. It will effectively drag
+ * the graph, and eventually zooms and turn it if the user is using two
+ * fingers.
+ *
+ * @param {event} e A touch event.
+ */
+ function _handleMove(e) {
+ if (!_doubleTap && _settings('touchEnabled')) {
+ var x0,
+ x1,
+ y0,
+ y1,
+ cos,
+ sin,
+ end,
+ pos0,
+ pos1,
+ diff,
+ start,
+ dAngle,
+ dRatio,
+ newStageX,
+ newStageY,
+ newStageRatio,
+ newStageAngle;
+
+ _downTouches = e.touches;
+ _isMoving = true;
+
+ if (_movingTimeoutId)
+ clearTimeout(_movingTimeoutId);
+
+ _movingTimeoutId = setTimeout(function() {
+ _isMoving = false;
+ }, _settings('dragTimeout'));
+
+ switch (_touchMode) {
+ case 1:
+ pos0 = position(_downTouches[0]);
+ x0 = pos0.x;
+ y0 = pos0.y;
+
+ diff = _camera.cameraPosition(
+ x0 - _startTouchX0,
+ y0 - _startTouchY0,
+ true
+ );
+
+ newStageX = _startCameraX - diff.x;
+ newStageY = _startCameraY - diff.y;
+
+ if (newStageX !== _camera.x || newStageY !== _camera.y) {
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+
+ _camera.goTo({
+ x: newStageX,
+ y: newStageY
+ });
+
+ _self.dispatchEvent('mousemove',
+ sigma.utils.mouseCoords(e, pos0.x, pos0.y));
+
+ _self.dispatchEvent('drag');
+ }
+ break;
+ case 2:
+ pos0 = position(_downTouches[0]);
+ pos1 = position(_downTouches[1]);
+ x0 = pos0.x;
+ y0 = pos0.y;
+ x1 = pos1.x;
+ y1 = pos1.y;
+
+ start = _camera.cameraPosition(
+ (_startTouchX0 + _startTouchX1) / 2 -
+ sigma.utils.getCenter(e).x,
+ (_startTouchY0 + _startTouchY1) / 2 -
+ sigma.utils.getCenter(e).y,
+ true
+ );
+ end = _camera.cameraPosition(
+ (x0 + x1) / 2 - sigma.utils.getCenter(e).x,
+ (y0 + y1) / 2 - sigma.utils.getCenter(e).y,
+ true
+ );
+
+ dAngle = Math.atan2(y1 - y0, x1 - x0) - _startTouchAngle;
+ dRatio = Math.sqrt(
+ (y1 - y0) * (y1 - y0) + (x1 - x0) * (x1 - x0)
+ ) / _startTouchDistance;
+
+ // Translation:
+ x0 = start.x;
+ y0 = start.y;
+
+ // Homothetic transformation:
+ newStageRatio = _startCameraRatio / dRatio;
+ x0 = x0 * dRatio;
+ y0 = y0 * dRatio;
+
+ // Rotation:
+ newStageAngle = _startCameraAngle - dAngle;
+ cos = Math.cos(-dAngle);
+ sin = Math.sin(-dAngle);
+ x1 = x0 * cos + y0 * sin;
+ y1 = y0 * cos - x0 * sin;
+ x0 = x1;
+ y0 = y1;
+
+ // Finalize:
+ newStageX = x0 - end.x + _startCameraX;
+ newStageY = y0 - end.y + _startCameraY;
+
+ if (
+ newStageRatio !== _camera.ratio ||
+ newStageAngle !== _camera.angle ||
+ newStageX !== _camera.x ||
+ newStageY !== _camera.y
+ ) {
+ _lastCameraX = _camera.x;
+ _lastCameraY = _camera.y;
+ _lastCameraAngle = _camera.angle;
+ _lastCameraRatio = _camera.ratio;
+
+ _camera.goTo({
+ x: newStageX,
+ y: newStageY,
+ angle: newStageAngle,
+ ratio: newStageRatio
+ });
+
+ _self.dispatchEvent('drag');
+ }
+
+ break;
+ }
+
+ e.preventDefault();
+ return false;
+ }
+ }
+
+ /**
+ * The handler listening to the double tap custom event. It will
+ * basically zoom into the graph.
+ *
+ * @param {event} e A touch event.
+ */
+ function _doubleTapHandler(e) {
+ var pos,
+ ratio,
+ animation;
+
+ if (e.touches && e.touches.length === 1 && _settings('touchEnabled')) {
+ _doubleTap = true;
+
+ ratio = 1 / _settings('doubleClickZoomingRatio');
+
+ pos = position(e.touches[0]);
+ _self.dispatchEvent('doubleclick',
+ sigma.utils.mouseCoords(e, pos.x, pos.y));
+
+ if (_settings('doubleClickEnabled')) {
+ pos = _camera.cameraPosition(
+ pos.x - sigma.utils.getCenter(e).x,
+ pos.y - sigma.utils.getCenter(e).y,
+ true
+ );
+
+ animation = {
+ duration: _settings('doubleClickZoomDuration'),
+ onComplete: function() {
+ _doubleTap = false;
+ }
+ };
+
+ sigma.utils.zoomTo(_camera, pos.x, pos.y, ratio, animation);
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+
+ e.stopPropagation();
+ return false;
+ }
+ }
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/classes/sigma.classes.camera.js b/blogContent/projects/steam/src/classes/sigma.classes.camera.js
new file mode 100644
index 0000000..dcc4c52
--- /dev/null
+++ b/blogContent/projects/steam/src/classes/sigma.classes.camera.js
@@ -0,0 +1,240 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ sigma.utils.pkg('sigma.classes');
+
+ /**
+ * The camera constructor. It just initializes its attributes and methods.
+ *
+ * @param {string} id The id.
+ * @param {sigma.classes.graph} graph The graph.
+ * @param {configurable} settings The settings function.
+ * @param {?object} options Eventually some overriding options.
+ * @return {camera} Returns the fresh new camera instance.
+ */
+ sigma.classes.camera = function(id, graph, settings, options) {
+ sigma.classes.dispatcher.extend(this);
+
+ Object.defineProperty(this, 'graph', {
+ value: graph
+ });
+ Object.defineProperty(this, 'id', {
+ value: id
+ });
+ Object.defineProperty(this, 'readPrefix', {
+ value: 'read_cam' + id + ':'
+ });
+ Object.defineProperty(this, 'prefix', {
+ value: 'cam' + id + ':'
+ });
+
+ this.x = 0;
+ this.y = 0;
+ this.ratio = 1;
+ this.angle = 0;
+ this.isAnimated = false;
+ this.settings = (typeof options === 'object' && options) ?
+ settings.embedObject(options) :
+ settings;
+ };
+
+ /**
+ * Updates the camera position.
+ *
+ * @param {object} coordinates The new coordinates object.
+ * @return {camera} Returns the camera.
+ */
+ sigma.classes.camera.prototype.goTo = function(coordinates) {
+ if (!this.settings('enableCamera'))
+ return this;
+
+ var i,
+ l,
+ c = coordinates || {},
+ keys = ['x', 'y', 'ratio', 'angle'];
+
+ for (i = 0, l = keys.length; i < l; i++)
+ if (c[keys[i]] !== undefined) {
+ if (typeof c[keys[i]] === 'number' && !isNaN(c[keys[i]]))
+ this[keys[i]] = c[keys[i]];
+ else
+ throw 'Value for "' + keys[i] + '" is not a number.';
+ }
+
+ this.dispatchEvent('coordinatesUpdated');
+ return this;
+ };
+
+ /**
+ * This method takes a graph and computes for each node and edges its
+ * coordinates relatively to the center of the camera. Basically, it will
+ * compute the coordinates that will be used by the graphic renderers.
+ *
+ * Since it should be possible to use different cameras and different
+ * renderers, it is possible to specify a prefix to put before the new
+ * coordinates (to get something like "node.camera1_x")
+ *
+ * @param {?string} read The prefix of the coordinates to read.
+ * @param {?string} write The prefix of the coordinates to write.
+ * @param {?object} options Eventually an object of options. Those can be:
+ * - A restricted nodes array.
+ * - A restricted edges array.
+ * - A width.
+ * - A height.
+ * @return {camera} Returns the camera.
+ */
+ sigma.classes.camera.prototype.applyView = function(read, write, options) {
+ options = options || {};
+ write = write !== undefined ? write : this.prefix;
+ read = read !== undefined ? read : this.readPrefix;
+
+ var nodes = options.nodes || this.graph.nodes(),
+ edges = options.edges || this.graph.edges();
+
+ var i,
+ l,
+ node,
+ relCos = Math.cos(this.angle) / this.ratio,
+ relSin = Math.sin(this.angle) / this.ratio,
+ nodeRatio = Math.pow(this.ratio, this.settings('nodesPowRatio')),
+ edgeRatio = Math.pow(this.ratio, this.settings('edgesPowRatio')),
+ xOffset = (options.width || 0) / 2 - this.x * relCos - this.y * relSin,
+ yOffset = (options.height || 0) / 2 - this.y * relCos + this.x * relSin;
+
+ for (i = 0, l = nodes.length; i < l; i++) {
+ node = nodes[i];
+ node[write + 'x'] =
+ (node[read + 'x'] || 0) * relCos +
+ (node[read + 'y'] || 0) * relSin +
+ xOffset;
+ node[write + 'y'] =
+ (node[read + 'y'] || 0) * relCos -
+ (node[read + 'x'] || 0) * relSin +
+ yOffset;
+ node[write + 'size'] =
+ (node[read + 'size'] || 0) /
+ nodeRatio;
+ }
+
+ for (i = 0, l = edges.length; i < l; i++) {
+ edges[i][write + 'size'] =
+ (edges[i][read + 'size'] || 0) /
+ edgeRatio;
+ }
+
+ return this;
+ };
+
+ /**
+ * This function converts the coordinates of a point from the frame of the
+ * camera to the frame of the graph.
+ *
+ * @param {number} x The X coordinate of the point in the frame of the
+ * camera.
+ * @param {number} y The Y coordinate of the point in the frame of the
+ * camera.
+ * @return {object} The point coordinates in the frame of the graph.
+ */
+ sigma.classes.camera.prototype.graphPosition = function(x, y, vector) {
+ var X = 0,
+ Y = 0,
+ cos = Math.cos(this.angle),
+ sin = Math.sin(this.angle);
+
+ // Revert the origin differential vector:
+ if (!vector) {
+ X = - (this.x * cos + this.y * sin) / this.ratio;
+ Y = - (this.y * cos - this.x * sin) / this.ratio;
+ }
+
+ return {
+ x: (x * cos + y * sin) / this.ratio + X,
+ y: (y * cos - x * sin) / this.ratio + Y
+ };
+ };
+
+ /**
+ * This function converts the coordinates of a point from the frame of the
+ * graph to the frame of the camera.
+ *
+ * @param {number} x The X coordinate of the point in the frame of the
+ * graph.
+ * @param {number} y The Y coordinate of the point in the frame of the
+ * graph.
+ * @return {object} The point coordinates in the frame of the camera.
+ */
+ sigma.classes.camera.prototype.cameraPosition = function(x, y, vector) {
+ var X = 0,
+ Y = 0,
+ cos = Math.cos(this.angle),
+ sin = Math.sin(this.angle);
+
+ // Revert the origin differential vector:
+ if (!vector) {
+ X = - (this.x * cos + this.y * sin) / this.ratio;
+ Y = - (this.y * cos - this.x * sin) / this.ratio;
+ }
+
+ return {
+ x: ((x - X) * cos - (y - Y) * sin) * this.ratio,
+ y: ((y - Y) * cos + (x - X) * sin) * this.ratio
+ };
+ };
+
+ /**
+ * This method returns the transformation matrix of the camera. This is
+ * especially useful to apply the camera view directly in shaders, in case of
+ * WebGL rendering.
+ *
+ * @return {array} The transformation matrix.
+ */
+ sigma.classes.camera.prototype.getMatrix = function() {
+ var scale = sigma.utils.matrices.scale(1 / this.ratio),
+ rotation = sigma.utils.matrices.rotation(this.angle),
+ translation = sigma.utils.matrices.translation(-this.x, -this.y),
+ matrix = sigma.utils.matrices.multiply(
+ translation,
+ sigma.utils.matrices.multiply(
+ rotation,
+ scale
+ )
+ );
+
+ return matrix;
+ };
+
+ /**
+ * Taking a width and a height as parameters, this method returns the
+ * coordinates of the rectangle representing the camera on screen, in the
+ * graph's referentiel.
+ *
+ * To keep displaying labels of nodes going out of the screen, the method
+ * keeps a margin around the screen in the returned rectangle.
+ *
+ * @param {number} width The width of the screen.
+ * @param {number} height The height of the screen.
+ * @return {object} The rectangle as x1, y1, x2 and y2, representing
+ * two opposite points.
+ */
+ sigma.classes.camera.prototype.getRectangle = function(width, height) {
+ var widthVect = this.cameraPosition(width, 0, true),
+ heightVect = this.cameraPosition(0, height, true),
+ centerVect = this.cameraPosition(width / 2, height / 2, true),
+ marginX = this.cameraPosition(width / 4, 0, true).x,
+ marginY = this.cameraPosition(0, height / 4, true).y;
+
+ return {
+ x1: this.x - centerVect.x - marginX,
+ y1: this.y - centerVect.y - marginY,
+ x2: this.x - centerVect.x + marginX + widthVect.x,
+ y2: this.y - centerVect.y - marginY + widthVect.y,
+ height: Math.sqrt(
+ Math.pow(heightVect.x, 2) +
+ Math.pow(heightVect.y + 2 * marginY, 2)
+ )
+ };
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/classes/sigma.classes.configurable.js b/blogContent/projects/steam/src/classes/sigma.classes.configurable.js
new file mode 100644
index 0000000..09ce1f7
--- /dev/null
+++ b/blogContent/projects/steam/src/classes/sigma.classes.configurable.js
@@ -0,0 +1,116 @@
+;(function() {
+ 'use strict';
+
+ /**
+ * This utils aims to facilitate the manipulation of each instance setting.
+ * Using a function instead of an object brings two main advantages: First,
+ * it will be easier in the future to catch settings updates through a
+ * function than an object. Second, giving it a full object will "merge" it
+ * to the settings object properly, keeping us to have to always add a loop.
+ *
+ * @return {configurable} The "settings" function.
+ */
+ var configurable = function() {
+ var i,
+ l,
+ data = {},
+ datas = Array.prototype.slice.call(arguments, 0);
+
+ /**
+ * The method to use to set or get any property of this instance.
+ *
+ * @param {string|object} a1 If it is a string and if a2 is undefined,
+ * then it will return the corresponding
+ * property. If it is a string and if a2 is
+ * set, then it will set a2 as the property
+ * corresponding to a1, and return this. If
+ * it is an object, then each pair string +
+ * object(or any other type) will be set as a
+ * property.
+ * @param {*?} a2 The new property corresponding to a1 if a1
+ * is a string.
+ * @return {*|configurable} Returns itself or the corresponding
+ * property.
+ *
+ * Polymorphism:
+ * *************
+ * Here are some basic use examples:
+ *
+ * > settings = new configurable();
+ * > settings('mySetting', 42);
+ * > settings('mySetting'); // Logs: 42
+ * > settings('mySetting', 123);
+ * > settings('mySetting'); // Logs: 123
+ * > settings({mySetting: 456});
+ * > settings('mySetting'); // Logs: 456
+ *
+ * Also, it is possible to use the function as a fallback:
+ * > settings({mySetting: 'abc'}, 'mySetting'); // Logs: 'abc'
+ * > settings({hisSetting: 'abc'}, 'mySetting'); // Logs: 456
+ */
+ var settings = function(a1, a2) {
+ var o,
+ i,
+ l,
+ k;
+
+ if (arguments.length === 1 && typeof a1 === 'string') {
+ if (data[a1] !== undefined)
+ return data[a1];
+ for (i = 0, l = datas.length; i < l; i++)
+ if (datas[i][a1] !== undefined)
+ return datas[i][a1];
+ return undefined;
+ } else if (typeof a1 === 'object' && typeof a2 === 'string') {
+ return (a1 || {})[a2] !== undefined ? a1[a2] : settings(a2);
+ } else {
+ o = (typeof a1 === 'object' && a2 === undefined) ? a1 : {};
+
+ if (typeof a1 === 'string')
+ o[a1] = a2;
+
+ for (i = 0, k = Object.keys(o), l = k.length; i < l; i++)
+ data[k[i]] = o[k[i]];
+
+ return this;
+ }
+ };
+
+ /**
+ * This method returns a new configurable function, with new objects
+ *
+ * @param {object*} Any number of objects to search in.
+ * @return {function} Returns the function. Check its documentation to know
+ * more about how it works.
+ */
+ settings.embedObjects = function() {
+ var args = datas.concat(
+ data
+ ).concat(
+ Array.prototype.splice.call(arguments, 0)
+ );
+
+ return configurable.apply({}, args);
+ };
+
+ // Initialize
+ for (i = 0, l = arguments.length; i < l; i++)
+ settings(arguments[i]);
+
+ return settings;
+ };
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined') {
+ this.sigma.classes = this.sigma.classes || {};
+ this.sigma.classes.configurable = configurable;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = configurable;
+ exports.configurable = configurable;
+ } else
+ this.configurable = configurable;
+}).call(this);
diff --git a/blogContent/projects/steam/src/classes/sigma.classes.dispatcher.js b/blogContent/projects/steam/src/classes/sigma.classes.dispatcher.js
new file mode 100644
index 0000000..0ce7dca
--- /dev/null
+++ b/blogContent/projects/steam/src/classes/sigma.classes.dispatcher.js
@@ -0,0 +1,204 @@
+;(function() {
+ 'use strict';
+
+ /**
+ * Dispatcher constructor.
+ *
+ * @return {dispatcher} The new dispatcher instance.
+ */
+ var dispatcher = function() {
+ Object.defineProperty(this, '_handlers', {
+ value: {}
+ });
+ };
+
+
+
+
+ /**
+ * Will execute the handler everytime that the indicated event (or the
+ * indicated events) will be triggered.
+ *
+ * @param {string} events The name of the event (or the events
+ * separated by spaces).
+ * @param {function(Object)} handler The handler to bind.
+ * @return {dispatcher} Returns the instance itself.
+ */
+ dispatcher.prototype.bind = function(events, handler) {
+ var i,
+ l,
+ event,
+ eArray;
+
+ if (
+ arguments.length === 1 &&
+ typeof arguments[0] === 'object'
+ )
+ for (events in arguments[0])
+ this.bind(events, arguments[0][events]);
+ else if (
+ arguments.length === 2 &&
+ typeof arguments[1] === 'function'
+ ) {
+ eArray = typeof events === 'string' ? events.split(' ') : events;
+
+ for (i = 0, l = eArray.length; i !== l; i += 1) {
+ event = eArray[i];
+
+ // Check that event is not '':
+ if (!event)
+ continue;
+
+ if (!this._handlers[event])
+ this._handlers[event] = [];
+
+ // Using an object instead of directly the handler will make possible
+ // later to add flags
+ this._handlers[event].push({
+ handler: handler
+ });
+ }
+ } else
+ throw 'bind: Wrong arguments.';
+
+ return this;
+ };
+
+ /**
+ * Removes the handler from a specified event (or specified events).
+ *
+ * @param {?string} events The name of the event (or the events
+ * separated by spaces). If undefined,
+ * then all handlers are removed.
+ * @param {?function(object)} handler The handler to unbind. If undefined,
+ * each handler bound to the event or the
+ * events will be removed.
+ * @return {dispatcher} Returns the instance itself.
+ */
+ dispatcher.prototype.unbind = function(events, handler) {
+ var i,
+ n,
+ j,
+ m,
+ k,
+ a,
+ event,
+ eArray = typeof events === 'string' ? events.split(' ') : events;
+
+ if (!arguments.length) {
+ for (k in this._handlers)
+ delete this._handlers[k];
+ return this;
+ }
+
+ if (handler) {
+ for (i = 0, n = eArray.length; i !== n; i += 1) {
+ event = eArray[i];
+ if (this._handlers[event]) {
+ a = [];
+ for (j = 0, m = this._handlers[event].length; j !== m; j += 1)
+ if (this._handlers[event][j].handler !== handler)
+ a.push(this._handlers[event][j]);
+
+ this._handlers[event] = a;
+ }
+
+ if (this._handlers[event] && this._handlers[event].length === 0)
+ delete this._handlers[event];
+ }
+ } else
+ for (i = 0, n = eArray.length; i !== n; i += 1)
+ delete this._handlers[eArray[i]];
+
+ return this;
+ };
+
+ /**
+ * Executes each handler bound to the event
+ *
+ * @param {string} events The name of the event (or the events separated
+ * by spaces).
+ * @param {?object} data The content of the event (optional).
+ * @return {dispatcher} Returns the instance itself.
+ */
+ dispatcher.prototype.dispatchEvent = function(events, data) {
+ var i,
+ n,
+ j,
+ m,
+ a,
+ event,
+ eventName,
+ self = this,
+ eArray = typeof events === 'string' ? events.split(' ') : events;
+
+ data = data === undefined ? {} : data;
+
+ for (i = 0, n = eArray.length; i !== n; i += 1) {
+ eventName = eArray[i];
+
+ if (this._handlers[eventName]) {
+ event = self.getEvent(eventName, data);
+ a = [];
+
+ for (j = 0, m = this._handlers[eventName].length; j !== m; j += 1) {
+ this._handlers[eventName][j].handler(event);
+ if (!this._handlers[eventName][j].one)
+ a.push(this._handlers[eventName][j]);
+ }
+
+ this._handlers[eventName] = a;
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Return an event object.
+ *
+ * @param {string} events The name of the event.
+ * @param {?object} data The content of the event (optional).
+ * @return {object} Returns the instance itself.
+ */
+ dispatcher.prototype.getEvent = function(event, data) {
+ return {
+ type: event,
+ data: data || {},
+ target: this
+ };
+ };
+
+ /**
+ * A useful function to deal with inheritance. It will make the target
+ * inherit the prototype of the class dispatcher as well as its constructor.
+ *
+ * @param {object} target The target.
+ */
+ dispatcher.extend = function(target, args) {
+ var k;
+
+ for (k in dispatcher.prototype)
+ if (dispatcher.prototype.hasOwnProperty(k))
+ target[k] = dispatcher.prototype[k];
+
+ dispatcher.apply(target, args);
+ };
+
+
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined') {
+ this.sigma.classes = this.sigma.classes || {};
+ this.sigma.classes.dispatcher = dispatcher;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = dispatcher;
+ exports.dispatcher = dispatcher;
+ } else
+ this.dispatcher = dispatcher;
+}).call(this);
diff --git a/blogContent/projects/steam/src/classes/sigma.classes.edgequad.js b/blogContent/projects/steam/src/classes/sigma.classes.edgequad.js
new file mode 100644
index 0000000..fbc5b7f
--- /dev/null
+++ b/blogContent/projects/steam/src/classes/sigma.classes.edgequad.js
@@ -0,0 +1,832 @@
+;(function(undefined) {
+ 'use strict';
+
+ /**
+ * Sigma Quadtree Module for edges
+ * ===============================
+ *
+ * Author: Sébastien Heymann,
+ * from the quad of Guillaume Plique (Yomguithereal)
+ * Version: 0.2
+ */
+
+
+
+ /**
+ * Quad Geometric Operations
+ * -------------------------
+ *
+ * A useful batch of geometric operations used by the quadtree.
+ */
+
+ var _geom = {
+
+ /**
+ * Transforms a graph node with x, y and size into an
+ * axis-aligned square.
+ *
+ * @param {object} A graph node with at least a point (x, y) and a size.
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ pointToSquare: function(n) {
+ return {
+ x1: n.x - n.size,
+ y1: n.y - n.size,
+ x2: n.x + n.size,
+ y2: n.y - n.size,
+ height: n.size * 2
+ };
+ },
+
+ /**
+ * Transforms a graph edge with x1, y1, x2, y2 and size into an
+ * axis-aligned square.
+ *
+ * @param {object} A graph edge with at least two points
+ * (x1, y1), (x2, y2) and a size.
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ lineToSquare: function(e) {
+ if (e.y1 < e.y2) {
+ // (e.x1, e.y1) on top
+ if (e.x1 < e.x2) {
+ // (e.x1, e.y1) on left
+ return {
+ x1: e.x1 - e.size,
+ y1: e.y1 - e.size,
+ x2: e.x2 + e.size,
+ y2: e.y1 - e.size,
+ height: e.y2 - e.y1 + e.size * 2
+ };
+ }
+ // (e.x1, e.y1) on right
+ return {
+ x1: e.x2 - e.size,
+ y1: e.y1 - e.size,
+ x2: e.x1 + e.size,
+ y2: e.y1 - e.size,
+ height: e.y2 - e.y1 + e.size * 2
+ };
+ }
+
+ // (e.x2, e.y2) on top
+ if (e.x1 < e.x2) {
+ // (e.x1, e.y1) on left
+ return {
+ x1: e.x1 - e.size,
+ y1: e.y2 - e.size,
+ x2: e.x2 + e.size,
+ y2: e.y2 - e.size,
+ height: e.y1 - e.y2 + e.size * 2
+ };
+ }
+ // (e.x2, e.y2) on right
+ return {
+ x1: e.x2 - e.size,
+ y1: e.y2 - e.size,
+ x2: e.x1 + e.size,
+ y2: e.y2 - e.size,
+ height: e.y1 - e.y2 + e.size * 2
+ };
+ },
+
+ /**
+ * Transforms a graph edge of type 'curve' with x1, y1, x2, y2,
+ * control point and size into an axis-aligned square.
+ *
+ * @param {object} e A graph edge with at least two points
+ * (x1, y1), (x2, y2) and a size.
+ * @param {object} cp A control point (x,y).
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ quadraticCurveToSquare: function(e, cp) {
+ var pt = sigma.utils.getPointOnQuadraticCurve(
+ 0.5,
+ e.x1,
+ e.y1,
+ e.x2,
+ e.y2,
+ cp.x,
+ cp.y
+ );
+
+ // Bounding box of the two points and the point at the middle of the
+ // curve:
+ var minX = Math.min(e.x1, e.x2, pt.x),
+ maxX = Math.max(e.x1, e.x2, pt.x),
+ minY = Math.min(e.y1, e.y2, pt.y),
+ maxY = Math.max(e.y1, e.y2, pt.y);
+
+ return {
+ x1: minX - e.size,
+ y1: minY - e.size,
+ x2: maxX + e.size,
+ y2: minY - e.size,
+ height: maxY - minY + e.size * 2
+ };
+ },
+
+ /**
+ * Transforms a graph self loop into an axis-aligned square.
+ *
+ * @param {object} n A graph node with a point (x, y) and a size.
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ selfLoopToSquare: function(n) {
+ // Fitting to the curve is too costly, we compute a larger bounding box
+ // using the control points:
+ var cp = sigma.utils.getSelfLoopControlPoints(n.x, n.y, n.size);
+
+ // Bounding box of the point and the two control points:
+ var minX = Math.min(n.x, cp.x1, cp.x2),
+ maxX = Math.max(n.x, cp.x1, cp.x2),
+ minY = Math.min(n.y, cp.y1, cp.y2),
+ maxY = Math.max(n.y, cp.y1, cp.y2);
+
+ return {
+ x1: minX - n.size,
+ y1: minY - n.size,
+ x2: maxX + n.size,
+ y2: minY - n.size,
+ height: maxY - minY + n.size * 2
+ };
+ },
+
+ /**
+ * Checks whether a rectangle is axis-aligned.
+ *
+ * @param {object} A rectangle defined by two points
+ * (x1, y1) and (x2, y2).
+ * @return {boolean} True if the rectangle is axis-aligned.
+ */
+ isAxisAligned: function(r) {
+ return r.x1 === r.x2 || r.y1 === r.y2;
+ },
+
+ /**
+ * Compute top points of an axis-aligned rectangle. This is useful in
+ * cases when the rectangle has been rotated (left, right or bottom up) and
+ * later operations need to know the top points.
+ *
+ * @param {object} An axis-aligned rectangle defined by two points
+ * (x1, y1), (x2, y2) and height.
+ * @return {object} A rectangle: two points (x1, y1), (x2, y2) and height.
+ */
+ axisAlignedTopPoints: function(r) {
+
+ // Basic
+ if (r.y1 === r.y2 && r.x1 < r.x2)
+ return r;
+
+ // Rotated to right
+ if (r.x1 === r.x2 && r.y2 > r.y1)
+ return {
+ x1: r.x1 - r.height, y1: r.y1,
+ x2: r.x1, y2: r.y1,
+ height: r.height
+ };
+
+ // Rotated to left
+ if (r.x1 === r.x2 && r.y2 < r.y1)
+ return {
+ x1: r.x1, y1: r.y2,
+ x2: r.x2 + r.height, y2: r.y2,
+ height: r.height
+ };
+
+ // Bottom's up
+ return {
+ x1: r.x2, y1: r.y1 - r.height,
+ x2: r.x1, y2: r.y1 - r.height,
+ height: r.height
+ };
+ },
+
+ /**
+ * Get coordinates of a rectangle's lower left corner from its top points.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @return {object} Coordinates of the corner (x, y).
+ */
+ lowerLeftCoor: function(r) {
+ var width = (
+ Math.sqrt(
+ Math.pow(r.x2 - r.x1, 2) +
+ Math.pow(r.y2 - r.y1, 2)
+ )
+ );
+
+ return {
+ x: r.x1 - (r.y2 - r.y1) * r.height / width,
+ y: r.y1 + (r.x2 - r.x1) * r.height / width
+ };
+ },
+
+ /**
+ * Get coordinates of a rectangle's lower right corner from its top points
+ * and its lower left corner.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @param {object} A corner's coordinates (x, y).
+ * @return {object} Coordinates of the corner (x, y).
+ */
+ lowerRightCoor: function(r, llc) {
+ return {
+ x: llc.x - r.x1 + r.x2,
+ y: llc.y - r.y1 + r.y2
+ };
+ },
+
+ /**
+ * Get the coordinates of all the corners of a rectangle from its top point.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @return {array} An array of the four corners' coordinates (x, y).
+ */
+ rectangleCorners: function(r) {
+ var llc = this.lowerLeftCoor(r),
+ lrc = this.lowerRightCoor(r, llc);
+
+ return [
+ {x: r.x1, y: r.y1},
+ {x: r.x2, y: r.y2},
+ {x: llc.x, y: llc.y},
+ {x: lrc.x, y: lrc.y}
+ ];
+ },
+
+ /**
+ * Split a square defined by its boundaries into four.
+ *
+ * @param {object} Boundaries of the square (x, y, width, height).
+ * @return {array} An array containing the four new squares, themselves
+ * defined by an array of their four corners (x, y).
+ */
+ splitSquare: function(b) {
+ return [
+ [
+ {x: b.x, y: b.y},
+ {x: b.x + b.width / 2, y: b.y},
+ {x: b.x, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2}
+ ],
+ [
+ {x: b.x + b.width / 2, y: b.y},
+ {x: b.x + b.width, y: b.y},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x + b.width, y: b.y + b.height / 2}
+ ],
+ [
+ {x: b.x, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x, y: b.y + b.height},
+ {x: b.x + b.width / 2, y: b.y + b.height}
+ ],
+ [
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x + b.width, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height},
+ {x: b.x + b.width, y: b.y + b.height}
+ ]
+ ];
+ },
+
+ /**
+ * Compute the four axis between corners of rectangle A and corners of
+ * rectangle B. This is needed later to check an eventual collision.
+ *
+ * @param {array} An array of rectangle A's four corners (x, y).
+ * @param {array} An array of rectangle B's four corners (x, y).
+ * @return {array} An array of four axis defined by their coordinates (x,y).
+ */
+ axis: function(c1, c2) {
+ return [
+ {x: c1[1].x - c1[0].x, y: c1[1].y - c1[0].y},
+ {x: c1[1].x - c1[3].x, y: c1[1].y - c1[3].y},
+ {x: c2[0].x - c2[2].x, y: c2[0].y - c2[2].y},
+ {x: c2[0].x - c2[1].x, y: c2[0].y - c2[1].y}
+ ];
+ },
+
+ /**
+ * Project a rectangle's corner on an axis.
+ *
+ * @param {object} Coordinates of a corner (x, y).
+ * @param {object} Coordinates of an axis (x, y).
+ * @return {object} The projection defined by coordinates (x, y).
+ */
+ projection: function(c, a) {
+ var l = (
+ (c.x * a.x + c.y * a.y) /
+ (Math.pow(a.x, 2) + Math.pow(a.y, 2))
+ );
+
+ return {
+ x: l * a.x,
+ y: l * a.y
+ };
+ },
+
+ /**
+ * Check whether two rectangles collide on one particular axis.
+ *
+ * @param {object} An axis' coordinates (x, y).
+ * @param {array} Rectangle A's corners.
+ * @param {array} Rectangle B's corners.
+ * @return {boolean} True if the rectangles collide on the axis.
+ */
+ axisCollision: function(a, c1, c2) {
+ var sc1 = [],
+ sc2 = [];
+
+ for (var ci = 0; ci < 4; ci++) {
+ var p1 = this.projection(c1[ci], a),
+ p2 = this.projection(c2[ci], a);
+
+ sc1.push(p1.x * a.x + p1.y * a.y);
+ sc2.push(p2.x * a.x + p2.y * a.y);
+ }
+
+ var maxc1 = Math.max.apply(Math, sc1),
+ maxc2 = Math.max.apply(Math, sc2),
+ minc1 = Math.min.apply(Math, sc1),
+ minc2 = Math.min.apply(Math, sc2);
+
+ return (minc2 <= maxc1 && maxc2 >= minc1);
+ },
+
+ /**
+ * Check whether two rectangles collide on each one of their four axis. If
+ * all axis collide, then the two rectangles do collide on the plane.
+ *
+ * @param {array} Rectangle A's corners.
+ * @param {array} Rectangle B's corners.
+ * @return {boolean} True if the rectangles collide.
+ */
+ collision: function(c1, c2) {
+ var axis = this.axis(c1, c2),
+ col = true;
+
+ for (var i = 0; i < 4; i++)
+ col = col && this.axisCollision(axis[i], c1, c2);
+
+ return col;
+ }
+ };
+
+
+ /**
+ * Quad Functions
+ * ------------
+ *
+ * The Quadtree functions themselves.
+ * For each of those functions, we consider that in a splitted quad, the
+ * index of each node is the following:
+ * 0: top left
+ * 1: top right
+ * 2: bottom left
+ * 3: bottom right
+ *
+ * Moreover, the hereafter quad's philosophy is to consider that if an element
+ * collides with more than one nodes, this element belongs to each of the
+ * nodes it collides with where other would let it lie on a higher node.
+ */
+
+ /**
+ * Get the index of the node containing the point in the quad
+ *
+ * @param {object} point A point defined by coordinates (x, y).
+ * @param {object} quadBounds Boundaries of the quad (x, y, width, heigth).
+ * @return {integer} The index of the node containing the point.
+ */
+ function _quadIndex(point, quadBounds) {
+ var xmp = quadBounds.x + quadBounds.width / 2,
+ ymp = quadBounds.y + quadBounds.height / 2,
+ top = (point.y < ymp),
+ left = (point.x < xmp);
+
+ if (top) {
+ if (left)
+ return 0;
+ else
+ return 1;
+ }
+ else {
+ if (left)
+ return 2;
+ else
+ return 3;
+ }
+ }
+
+ /**
+ * Get a list of indexes of nodes containing an axis-aligned rectangle
+ *
+ * @param {object} rectangle A rectangle defined by two points (x1, y1),
+ * (x2, y2) and height.
+ * @param {array} quadCorners An array of the quad nodes' corners.
+ * @return {array} An array of indexes containing one to
+ * four integers.
+ */
+ function _quadIndexes(rectangle, quadCorners) {
+ var indexes = [];
+
+ // Iterating through quads
+ for (var i = 0; i < 4; i++)
+ if ((rectangle.x2 >= quadCorners[i][0].x) &&
+ (rectangle.x1 <= quadCorners[i][1].x) &&
+ (rectangle.y1 + rectangle.height >= quadCorners[i][0].y) &&
+ (rectangle.y1 <= quadCorners[i][2].y))
+ indexes.push(i);
+
+ return indexes;
+ }
+
+ /**
+ * Get a list of indexes of nodes containing a non-axis-aligned rectangle
+ *
+ * @param {array} corners An array containing each corner of the
+ * rectangle defined by its coordinates (x, y).
+ * @param {array} quadCorners An array of the quad nodes' corners.
+ * @return {array} An array of indexes containing one to
+ * four integers.
+ */
+ function _quadCollision(corners, quadCorners) {
+ var indexes = [];
+
+ // Iterating through quads
+ for (var i = 0; i < 4; i++)
+ if (_geom.collision(corners, quadCorners[i]))
+ indexes.push(i);
+
+ return indexes;
+ }
+
+ /**
+ * Subdivide a quad by creating a node at a precise index. The function does
+ * not generate all four nodes not to potentially create unused nodes.
+ *
+ * @param {integer} index The index of the node to create.
+ * @param {object} quad The quad object to subdivide.
+ * @return {object} A new quad representing the node created.
+ */
+ function _quadSubdivide(index, quad) {
+ var next = quad.level + 1,
+ subw = Math.round(quad.bounds.width / 2),
+ subh = Math.round(quad.bounds.height / 2),
+ qx = Math.round(quad.bounds.x),
+ qy = Math.round(quad.bounds.y),
+ x,
+ y;
+
+ switch (index) {
+ case 0:
+ x = qx;
+ y = qy;
+ break;
+ case 1:
+ x = qx + subw;
+ y = qy;
+ break;
+ case 2:
+ x = qx;
+ y = qy + subh;
+ break;
+ case 3:
+ x = qx + subw;
+ y = qy + subh;
+ break;
+ }
+
+ return _quadTree(
+ {x: x, y: y, width: subw, height: subh},
+ next,
+ quad.maxElements,
+ quad.maxLevel
+ );
+ }
+
+ /**
+ * Recursively insert an element into the quadtree. Only points
+ * with size, i.e. axis-aligned squares, may be inserted with this
+ * method.
+ *
+ * @param {object} el The element to insert in the quadtree.
+ * @param {object} sizedPoint A sized point defined by two top points
+ * (x1, y1), (x2, y2) and height.
+ * @param {object} quad The quad in which to insert the element.
+ * @return {undefined} The function does not return anything.
+ */
+ function _quadInsert(el, sizedPoint, quad) {
+ if (quad.level < quad.maxLevel) {
+
+ // Searching appropriate quads
+ var indexes = _quadIndexes(sizedPoint, quad.corners);
+
+ // Iterating
+ for (var i = 0, l = indexes.length; i < l; i++) {
+
+ // Subdividing if necessary
+ if (quad.nodes[indexes[i]] === undefined)
+ quad.nodes[indexes[i]] = _quadSubdivide(indexes[i], quad);
+
+ // Recursion
+ _quadInsert(el, sizedPoint, quad.nodes[indexes[i]]);
+ }
+ }
+ else {
+
+ // Pushing the element in a leaf node
+ quad.elements.push(el);
+ }
+ }
+
+ /**
+ * Recursively retrieve every elements held by the node containing the
+ * searched point.
+ *
+ * @param {object} point The searched point (x, y).
+ * @param {object} quad The searched quad.
+ * @return {array} An array of elements contained in the relevant
+ * node.
+ */
+ function _quadRetrievePoint(point, quad) {
+ if (quad.level < quad.maxLevel) {
+ var index = _quadIndex(point, quad.bounds);
+
+ // If node does not exist we return an empty list
+ if (quad.nodes[index] !== undefined) {
+ return _quadRetrievePoint(point, quad.nodes[index]);
+ }
+ else {
+ return [];
+ }
+ }
+ else {
+ return quad.elements;
+ }
+ }
+
+ /**
+ * Recursively retrieve every elements contained within an rectangular area
+ * that may or may not be axis-aligned.
+ *
+ * @param {object|array} rectData The searched area defined either by
+ * an array of four corners (x, y) in
+ * the case of a non-axis-aligned
+ * rectangle or an object with two top
+ * points (x1, y1), (x2, y2) and height.
+ * @param {object} quad The searched quad.
+ * @param {function} collisionFunc The collision function used to search
+ * for node indexes.
+ * @param {array?} els The retrieved elements.
+ * @return {array} An array of elements contained in the
+ * area.
+ */
+ function _quadRetrieveArea(rectData, quad, collisionFunc, els) {
+ els = els || {};
+
+ if (quad.level < quad.maxLevel) {
+ var indexes = collisionFunc(rectData, quad.corners);
+
+ for (var i = 0, l = indexes.length; i < l; i++)
+ if (quad.nodes[indexes[i]] !== undefined)
+ _quadRetrieveArea(
+ rectData,
+ quad.nodes[indexes[i]],
+ collisionFunc,
+ els
+ );
+ } else
+ for (var j = 0, m = quad.elements.length; j < m; j++)
+ if (els[quad.elements[j].id] === undefined)
+ els[quad.elements[j].id] = quad.elements[j];
+
+ return els;
+ }
+
+ /**
+ * Creates the quadtree object itself.
+ *
+ * @param {object} bounds The boundaries of the quad defined by an
+ * origin (x, y), width and heigth.
+ * @param {integer} level The level of the quad in the tree.
+ * @param {integer} maxElements The max number of element in a leaf node.
+ * @param {integer} maxLevel The max recursion level of the tree.
+ * @return {object} The quadtree object.
+ */
+ function _quadTree(bounds, level, maxElements, maxLevel) {
+ return {
+ level: level || 0,
+ bounds: bounds,
+ corners: _geom.splitSquare(bounds),
+ maxElements: maxElements || 40,
+ maxLevel: maxLevel || 8,
+ elements: [],
+ nodes: []
+ };
+ }
+
+
+ /**
+ * Sigma Quad Constructor
+ * ----------------------
+ *
+ * The edgequad API as exposed to sigma.
+ */
+
+ /**
+ * The edgequad core that will become the sigma interface with the quadtree.
+ *
+ * property {object} _tree Property holding the quadtree object.
+ * property {object} _geom Exposition of the _geom namespace for testing.
+ * property {object} _cache Cache for the area method.
+ * property {boolean} _enabled Can index and retreive elements.
+ */
+ var edgequad = function() {
+ this._geom = _geom;
+ this._tree = null;
+ this._cache = {
+ query: false,
+ result: false
+ };
+ this._enabled = true;
+ };
+
+ /**
+ * Index a graph by inserting its edges into the quadtree.
+ *
+ * @param {object} graph A graph instance.
+ * @param {object} params An object of parameters with at least the quad
+ * bounds.
+ * @return {object} The quadtree object.
+ *
+ * Parameters:
+ * ----------
+ * bounds: {object} boundaries of the quad defined by its origin (x, y)
+ * width and heigth.
+ * prefix: {string?} a prefix for edge geometric attributes.
+ * maxElements: {integer?} the max number of elements in a leaf node.
+ * maxLevel: {integer?} the max recursion level of the tree.
+ */
+ edgequad.prototype.index = function(graph, params) {
+ if (!this._enabled)
+ return this._tree;
+
+ // Enforcing presence of boundaries
+ if (!params.bounds)
+ throw 'sigma.classes.edgequad.index: bounds information not given.';
+
+ // Prefix
+ var prefix = params.prefix || '',
+ cp,
+ source,
+ target,
+ n,
+ e;
+
+ // Building the tree
+ this._tree = _quadTree(
+ params.bounds,
+ 0,
+ params.maxElements,
+ params.maxLevel
+ );
+
+ var edges = graph.edges();
+
+ // Inserting graph edges into the tree
+ for (var i = 0, l = edges.length; i < l; i++) {
+ source = graph.nodes(edges[i].source);
+ target = graph.nodes(edges[i].target);
+ e = {
+ x1: source[prefix + 'x'],
+ y1: source[prefix + 'y'],
+ x2: target[prefix + 'x'],
+ y2: target[prefix + 'y'],
+ size: edges[i][prefix + 'size'] || 0
+ };
+
+ // Inserting edge
+ if (edges[i].type === 'curve' || edges[i].type === 'curvedArrow') {
+ if (source.id === target.id) {
+ n = {
+ x: source[prefix + 'x'],
+ y: source[prefix + 'y'],
+ size: source[prefix + 'size'] || 0
+ };
+ _quadInsert(
+ edges[i],
+ _geom.selfLoopToSquare(n),
+ this._tree);
+ }
+ else {
+ cp = sigma.utils.getQuadraticControlPoint(e.x1, e.y1, e.x2, e.y2);
+ _quadInsert(
+ edges[i],
+ _geom.quadraticCurveToSquare(e, cp),
+ this._tree);
+ }
+ }
+ else {
+ _quadInsert(
+ edges[i],
+ _geom.lineToSquare(e),
+ this._tree);
+ }
+ }
+
+ // Reset cache:
+ this._cache = {
+ query: false,
+ result: false
+ };
+
+ // remove?
+ return this._tree;
+ };
+
+ /**
+ * Retrieve every graph edges held by the quadtree node containing the
+ * searched point.
+ *
+ * @param {number} x of the point.
+ * @param {number} y of the point.
+ * @return {array} An array of edges retrieved.
+ */
+ edgequad.prototype.point = function(x, y) {
+ if (!this._enabled)
+ return [];
+
+ return this._tree ?
+ _quadRetrievePoint({x: x, y: y}, this._tree) || [] :
+ [];
+ };
+
+ /**
+ * Retrieve every graph edges within a rectangular area. The methods keep the
+ * last area queried in cache for optimization reason and will act differently
+ * for the same reason if the area is axis-aligned or not.
+ *
+ * @param {object} A rectangle defined by two top points (x1, y1), (x2, y2)
+ * and height.
+ * @return {array} An array of edges retrieved.
+ */
+ edgequad.prototype.area = function(rect) {
+ if (!this._enabled)
+ return [];
+
+ var serialized = JSON.stringify(rect),
+ collisionFunc,
+ rectData;
+
+ // Returning cache?
+ if (this._cache.query === serialized)
+ return this._cache.result;
+
+ // Axis aligned ?
+ if (_geom.isAxisAligned(rect)) {
+ collisionFunc = _quadIndexes;
+ rectData = _geom.axisAlignedTopPoints(rect);
+ }
+ else {
+ collisionFunc = _quadCollision;
+ rectData = _geom.rectangleCorners(rect);
+ }
+
+ // Retrieving edges
+ var edges = this._tree ?
+ _quadRetrieveArea(
+ rectData,
+ this._tree,
+ collisionFunc
+ ) :
+ [];
+
+ // Object to array
+ var edgesArray = [];
+ for (var i in edges)
+ edgesArray.push(edges[i]);
+
+ // Caching
+ this._cache.query = serialized;
+ this._cache.result = edgesArray;
+
+ return edgesArray;
+ };
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined') {
+ this.sigma.classes = this.sigma.classes || {};
+ this.sigma.classes.edgequad = edgequad;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = edgequad;
+ exports.edgequad = edgequad;
+ } else
+ this.edgequad = edgequad;
+}).call(this);
diff --git a/blogContent/projects/steam/src/classes/sigma.classes.graph.js b/blogContent/projects/steam/src/classes/sigma.classes.graph.js
new file mode 100644
index 0000000..c7ebe9d
--- /dev/null
+++ b/blogContent/projects/steam/src/classes/sigma.classes.graph.js
@@ -0,0 +1,859 @@
+;(function(undefined) {
+ 'use strict';
+
+ var _methods = Object.create(null),
+ _indexes = Object.create(null),
+ _initBindings = Object.create(null),
+ _methodBindings = Object.create(null),
+ _methodBeforeBindings = Object.create(null),
+ _defaultSettings = {
+ immutable: true,
+ clone: true
+ },
+ _defaultSettingsFunction = function(key) {
+ return _defaultSettings[key];
+ };
+
+ /**
+ * The graph constructor. It initializes the data and the indexes, and binds
+ * the custom indexes and methods to its own scope.
+ *
+ * Recognized parameters:
+ * **********************
+ * Here is the exhaustive list of every accepted parameters in the settings
+ * object:
+ *
+ * {boolean} clone Indicates if the data have to be cloned in methods
+ * to add nodes or edges.
+ * {boolean} immutable Indicates if nodes "id" values and edges "id",
+ * "source" and "target" values must be set as
+ * immutable.
+ *
+ * @param {?configurable} settings Eventually a settings function.
+ * @return {graph} The new graph instance.
+ */
+ var graph = function(settings) {
+ var k,
+ fn,
+ data;
+
+ /**
+ * DATA:
+ * *****
+ * Every data that is callable from graph methods are stored in this "data"
+ * object. This object will be served as context for all these methods,
+ * and it is possible to add other type of data in it.
+ */
+ data = {
+ /**
+ * SETTINGS FUNCTION:
+ * ******************
+ */
+ settings: settings || _defaultSettingsFunction,
+
+ /**
+ * MAIN DATA:
+ * **********
+ */
+ nodesArray: [],
+ edgesArray: [],
+
+ /**
+ * GLOBAL INDEXES:
+ * ***************
+ * These indexes just index data by ids.
+ */
+ nodesIndex: Object.create(null),
+ edgesIndex: Object.create(null),
+
+ /**
+ * LOCAL INDEXES:
+ * **************
+ * These indexes refer from node to nodes. Each key is an id, and each
+ * value is the array of the ids of related nodes.
+ */
+ inNeighborsIndex: Object.create(null),
+ outNeighborsIndex: Object.create(null),
+ allNeighborsIndex: Object.create(null),
+
+ inNeighborsCount: Object.create(null),
+ outNeighborsCount: Object.create(null),
+ allNeighborsCount: Object.create(null)
+ };
+
+ // Execute bindings:
+ for (k in _initBindings)
+ _initBindings[k].call(data);
+
+ // Add methods to both the scope and the data objects:
+ for (k in _methods) {
+ fn = __bindGraphMethod(k, data, _methods[k]);
+ this[k] = fn;
+ data[k] = fn;
+ }
+ };
+
+
+
+
+ /**
+ * A custom tool to bind methods such that function that are bound to it will
+ * be executed anytime the method is called.
+ *
+ * @param {string} methodName The name of the method to bind.
+ * @param {object} scope The scope where the method must be executed.
+ * @param {function} fn The method itself.
+ * @return {function} The new method.
+ */
+ function __bindGraphMethod(methodName, scope, fn) {
+ var result = function() {
+ var k,
+ res;
+
+ // Execute "before" bound functions:
+ for (k in _methodBeforeBindings[methodName])
+ _methodBeforeBindings[methodName][k].apply(scope, arguments);
+
+ // Apply the method:
+ res = fn.apply(scope, arguments);
+
+ // Execute bound functions:
+ for (k in _methodBindings[methodName])
+ _methodBindings[methodName][k].apply(scope, arguments);
+
+ // Return res:
+ return res;
+ };
+
+ return result;
+ }
+
+ /**
+ * This custom tool function removes every pair key/value from an hash. The
+ * goal is to avoid creating a new object while some other references are
+ * still hanging in some scopes...
+ *
+ * @param {object} obj The object to empty.
+ * @return {object} The empty object.
+ */
+ function __emptyObject(obj) {
+ var k;
+
+ for (k in obj)
+ if (!('hasOwnProperty' in obj) || obj.hasOwnProperty(k))
+ delete obj[k];
+
+ return obj;
+ }
+
+
+
+
+ /**
+ * This global method adds a method that will be bound to the futurly created
+ * graph instances.
+ *
+ * Since these methods will be bound to their scope when the instances are
+ * created, it does not use the prototype. Because of that, methods have to
+ * be added before instances are created to make them available.
+ *
+ * Here is an example:
+ *
+ * > graph.addMethod('getNodesCount', function() {
+ * > return this.nodesArray.length;
+ * > });
+ * >
+ * > var myGraph = new graph();
+ * > console.log(myGraph.getNodesCount()); // outputs 0
+ *
+ * @param {string} methodName The name of the method.
+ * @param {function} fn The method itself.
+ * @return {object} The global graph constructor.
+ */
+ graph.addMethod = function(methodName, fn) {
+ if (
+ typeof methodName !== 'string' ||
+ typeof fn !== 'function' ||
+ arguments.length !== 2
+ )
+ throw 'addMethod: Wrong arguments.';
+
+ if (_methods[methodName] || graph[methodName])
+ throw 'The method "' + methodName + '" already exists.';
+
+ _methods[methodName] = fn;
+ _methodBindings[methodName] = Object.create(null);
+ _methodBeforeBindings[methodName] = Object.create(null);
+
+ return this;
+ };
+
+ /**
+ * This global method returns true if the method has already been added, and
+ * false else.
+ *
+ * Here are some examples:
+ *
+ * > graph.hasMethod('addNode'); // returns true
+ * > graph.hasMethod('hasMethod'); // returns true
+ * > graph.hasMethod('unexistingMethod'); // returns false
+ *
+ * @param {string} methodName The name of the method.
+ * @return {boolean} The result.
+ */
+ graph.hasMethod = function(methodName) {
+ return !!(_methods[methodName] || graph[methodName]);
+ };
+
+ /**
+ * This global methods attaches a function to a method. Anytime the specified
+ * method is called, the attached function is called right after, with the
+ * same arguments and in the same scope. The attached function is called
+ * right before if the last argument is true, unless the method is the graph
+ * constructor.
+ *
+ * To attach a function to the graph constructor, use 'constructor' as the
+ * method name (first argument).
+ *
+ * The main idea is to have a clean way to keep custom indexes up to date,
+ * for instance:
+ *
+ * > var timesAddNodeCalled = 0;
+ * > graph.attach('addNode', 'timesAddNodeCalledInc', function() {
+ * > timesAddNodeCalled++;
+ * > });
+ * >
+ * > var myGraph = new graph();
+ * > console.log(timesAddNodeCalled); // outputs 0
+ * >
+ * > myGraph.addNode({ id: '1' }).addNode({ id: '2' });
+ * > console.log(timesAddNodeCalled); // outputs 2
+ *
+ * The idea for calling a function before is to provide pre-processors, for
+ * instance:
+ *
+ * > var colorPalette = { Person: '#C3CBE1', Place: '#9BDEBD' };
+ * > graph.attach('addNode', 'applyNodeColorPalette', function(n) {
+ * > n.color = colorPalette[n.category];
+ * > }, true);
+ * >
+ * > var myGraph = new graph();
+ * > myGraph.addNode({ id: 'n0', category: 'Person' });
+ * > console.log(myGraph.nodes('n0').color); // outputs '#C3CBE1'
+ *
+ * @param {string} methodName The name of the related method or
+ * "constructor".
+ * @param {string} key The key to identify the function to attach.
+ * @param {function} fn The function to bind.
+ * @param {boolean} before If true the function is called right before.
+ * @return {object} The global graph constructor.
+ */
+ graph.attach = function(methodName, key, fn, before) {
+ if (
+ typeof methodName !== 'string' ||
+ typeof key !== 'string' ||
+ typeof fn !== 'function' ||
+ arguments.length < 3 ||
+ arguments.length > 4
+ )
+ throw 'attach: Wrong arguments.';
+
+ var bindings;
+
+ if (methodName === 'constructor')
+ bindings = _initBindings;
+ else {
+ if (before) {
+ if (!_methodBeforeBindings[methodName])
+ throw 'The method "' + methodName + '" does not exist.';
+
+ bindings = _methodBeforeBindings[methodName];
+ }
+ else {
+ if (!_methodBindings[methodName])
+ throw 'The method "' + methodName + '" does not exist.';
+
+ bindings = _methodBindings[methodName];
+ }
+ }
+
+ if (bindings[key])
+ throw 'A function "' + key + '" is already attached ' +
+ 'to the method "' + methodName + '".';
+
+ bindings[key] = fn;
+
+ return this;
+ };
+
+ /**
+ * Alias of attach(methodName, key, fn, true).
+ */
+ graph.attachBefore = function(methodName, key, fn) {
+ return this.attach(methodName, key, fn, true);
+ };
+
+ /**
+ * This methods is just an helper to deal with custom indexes. It takes as
+ * arguments the name of the index and an object containing all the different
+ * functions to bind to the methods.
+ *
+ * Here is a basic example, that creates an index to keep the number of nodes
+ * in the current graph. It also adds a method to provide a getter on that
+ * new index:
+ *
+ * > sigma.classes.graph.addIndex('nodesCount', {
+ * > constructor: function() {
+ * > this.nodesCount = 0;
+ * > },
+ * > addNode: function() {
+ * > this.nodesCount++;
+ * > },
+ * > dropNode: function() {
+ * > this.nodesCount--;
+ * > }
+ * > });
+ * >
+ * > sigma.classes.graph.addMethod('getNodesCount', function() {
+ * > return this.nodesCount;
+ * > });
+ * >
+ * > var myGraph = new sigma.classes.graph();
+ * > console.log(myGraph.getNodesCount()); // outputs 0
+ * >
+ * > myGraph.addNode({ id: '1' }).addNode({ id: '2' });
+ * > console.log(myGraph.getNodesCount()); // outputs 2
+ *
+ * @param {string} name The name of the index.
+ * @param {object} bindings The object containing the functions to bind.
+ * @return {object} The global graph constructor.
+ */
+ graph.addIndex = function(name, bindings) {
+ if (
+ typeof name !== 'string' ||
+ Object(bindings) !== bindings ||
+ arguments.length !== 2
+ )
+ throw 'addIndex: Wrong arguments.';
+
+ if (_indexes[name])
+ throw 'The index "' + name + '" already exists.';
+
+ var k;
+
+ // Store the bindings:
+ _indexes[name] = bindings;
+
+ // Attach the bindings:
+ for (k in bindings)
+ if (typeof bindings[k] !== 'function')
+ throw 'The bindings must be functions.';
+ else
+ graph.attach(k, name, bindings[k]);
+
+ return this;
+ };
+
+
+
+
+ /**
+ * This method adds a node to the graph. The node must be an object, with a
+ * string under the key "id". Except for this, it is possible to add any
+ * other attribute, that will be preserved all along the manipulations.
+ *
+ * If the graph option "clone" has a truthy value, the node will be cloned
+ * when added to the graph. Also, if the graph option "immutable" has a
+ * truthy value, its id will be defined as immutable.
+ *
+ * @param {object} node The node to add.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('addNode', function(node) {
+ // Check that the node is an object and has an id:
+ if (Object(node) !== node || arguments.length !== 1)
+ throw 'addNode: Wrong arguments.';
+
+ if (typeof node.id !== 'string' && typeof node.id !== 'number')
+ throw 'The node must have a string or number id.';
+
+ if (this.nodesIndex[node.id])
+ throw 'The node "' + node.id + '" already exists.';
+
+ var k,
+ id = node.id,
+ validNode = Object.create(null);
+
+ // Check the "clone" option:
+ if (this.settings('clone')) {
+ for (k in node)
+ if (k !== 'id')
+ validNode[k] = node[k];
+ } else
+ validNode = node;
+
+ // Check the "immutable" option:
+ if (this.settings('immutable'))
+ Object.defineProperty(validNode, 'id', {
+ value: id,
+ enumerable: true
+ });
+ else
+ validNode.id = id;
+
+ // Add empty containers for edges indexes:
+ this.inNeighborsIndex[id] = Object.create(null);
+ this.outNeighborsIndex[id] = Object.create(null);
+ this.allNeighborsIndex[id] = Object.create(null);
+
+ this.inNeighborsCount[id] = 0;
+ this.outNeighborsCount[id] = 0;
+ this.allNeighborsCount[id] = 0;
+
+ // Add the node to indexes:
+ this.nodesArray.push(validNode);
+ this.nodesIndex[validNode.id] = validNode;
+
+ // Return the current instance:
+ return this;
+ });
+
+ /**
+ * This method adds an edge to the graph. The edge must be an object, with a
+ * string under the key "id", and strings under the keys "source" and
+ * "target" that design existing nodes. Except for this, it is possible to
+ * add any other attribute, that will be preserved all along the
+ * manipulations.
+ *
+ * If the graph option "clone" has a truthy value, the edge will be cloned
+ * when added to the graph. Also, if the graph option "immutable" has a
+ * truthy value, its id, source and target will be defined as immutable.
+ *
+ * @param {object} edge The edge to add.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('addEdge', function(edge) {
+ // Check that the edge is an object and has an id:
+ if (Object(edge) !== edge || arguments.length !== 1)
+ throw 'addEdge: Wrong arguments.';
+
+ if (typeof edge.id !== 'string' && typeof edge.id !== 'number')
+ throw 'The edge must have a string or number id.';
+
+ if ((typeof edge.source !== 'string' && typeof edge.source !== 'number') ||
+ !this.nodesIndex[edge.source])
+ throw 'The edge source must have an existing node id.';
+
+ if ((typeof edge.target !== 'string' && typeof edge.target !== 'number') ||
+ !this.nodesIndex[edge.target])
+ throw 'The edge target must have an existing node id.';
+
+ if (this.edgesIndex[edge.id])
+ throw 'The edge "' + edge.id + '" already exists.';
+
+ var k,
+ validEdge = Object.create(null);
+
+ // Check the "clone" option:
+ if (this.settings('clone')) {
+ for (k in edge)
+ if (k !== 'id' && k !== 'source' && k !== 'target')
+ validEdge[k] = edge[k];
+ } else
+ validEdge = edge;
+
+ // Check the "immutable" option:
+ if (this.settings('immutable')) {
+ Object.defineProperty(validEdge, 'id', {
+ value: edge.id,
+ enumerable: true
+ });
+
+ Object.defineProperty(validEdge, 'source', {
+ value: edge.source,
+ enumerable: true
+ });
+
+ Object.defineProperty(validEdge, 'target', {
+ value: edge.target,
+ enumerable: true
+ });
+ } else {
+ validEdge.id = edge.id;
+ validEdge.source = edge.source;
+ validEdge.target = edge.target;
+ }
+
+ // Add the edge to indexes:
+ this.edgesArray.push(validEdge);
+ this.edgesIndex[validEdge.id] = validEdge;
+
+ if (!this.inNeighborsIndex[validEdge.target][validEdge.source])
+ this.inNeighborsIndex[validEdge.target][validEdge.source] =
+ Object.create(null);
+ this.inNeighborsIndex[validEdge.target][validEdge.source][validEdge.id] =
+ validEdge;
+
+ if (!this.outNeighborsIndex[validEdge.source][validEdge.target])
+ this.outNeighborsIndex[validEdge.source][validEdge.target] =
+ Object.create(null);
+ this.outNeighborsIndex[validEdge.source][validEdge.target][validEdge.id] =
+ validEdge;
+
+ if (!this.allNeighborsIndex[validEdge.source][validEdge.target])
+ this.allNeighborsIndex[validEdge.source][validEdge.target] =
+ Object.create(null);
+ this.allNeighborsIndex[validEdge.source][validEdge.target][validEdge.id] =
+ validEdge;
+
+ if (validEdge.target !== validEdge.source) {
+ if (!this.allNeighborsIndex[validEdge.target][validEdge.source])
+ this.allNeighborsIndex[validEdge.target][validEdge.source] =
+ Object.create(null);
+ this.allNeighborsIndex[validEdge.target][validEdge.source][validEdge.id] =
+ validEdge;
+ }
+
+ // Keep counts up to date:
+ this.inNeighborsCount[validEdge.target]++;
+ this.outNeighborsCount[validEdge.source]++;
+ this.allNeighborsCount[validEdge.target]++;
+ this.allNeighborsCount[validEdge.source]++;
+
+ return this;
+ });
+
+ /**
+ * This method drops a node from the graph. It also removes each edge that is
+ * bound to it, through the dropEdge method. An error is thrown if the node
+ * does not exist.
+ *
+ * @param {string} id The node id.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('dropNode', function(id) {
+ // Check that the arguments are valid:
+ if ((typeof id !== 'string' && typeof id !== 'number') ||
+ arguments.length !== 1)
+ throw 'dropNode: Wrong arguments.';
+
+ if (!this.nodesIndex[id])
+ throw 'The node "' + id + '" does not exist.';
+
+ var i, k, l;
+
+ // Remove the node from indexes:
+ delete this.nodesIndex[id];
+ for (i = 0, l = this.nodesArray.length; i < l; i++)
+ if (this.nodesArray[i].id === id) {
+ this.nodesArray.splice(i, 1);
+ break;
+ }
+
+ // Remove related edges:
+ for (i = this.edgesArray.length - 1; i >= 0; i--)
+ if (this.edgesArray[i].source === id || this.edgesArray[i].target === id)
+ this.dropEdge(this.edgesArray[i].id);
+
+ // Remove related edge indexes:
+ delete this.inNeighborsIndex[id];
+ delete this.outNeighborsIndex[id];
+ delete this.allNeighborsIndex[id];
+
+ delete this.inNeighborsCount[id];
+ delete this.outNeighborsCount[id];
+ delete this.allNeighborsCount[id];
+
+ for (k in this.nodesIndex) {
+ delete this.inNeighborsIndex[k][id];
+ delete this.outNeighborsIndex[k][id];
+ delete this.allNeighborsIndex[k][id];
+ }
+
+ return this;
+ });
+
+ /**
+ * This method drops an edge from the graph. An error is thrown if the edge
+ * does not exist.
+ *
+ * @param {string} id The edge id.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('dropEdge', function(id) {
+ // Check that the arguments are valid:
+ if ((typeof id !== 'string' && typeof id !== 'number') ||
+ arguments.length !== 1)
+ throw 'dropEdge: Wrong arguments.';
+
+ if (!this.edgesIndex[id])
+ throw 'The edge "' + id + '" does not exist.';
+
+ var i, l, edge;
+
+ // Remove the edge from indexes:
+ edge = this.edgesIndex[id];
+ delete this.edgesIndex[id];
+ for (i = 0, l = this.edgesArray.length; i < l; i++)
+ if (this.edgesArray[i].id === id) {
+ this.edgesArray.splice(i, 1);
+ break;
+ }
+
+ delete this.inNeighborsIndex[edge.target][edge.source][edge.id];
+ if (!Object.keys(this.inNeighborsIndex[edge.target][edge.source]).length)
+ delete this.inNeighborsIndex[edge.target][edge.source];
+
+ delete this.outNeighborsIndex[edge.source][edge.target][edge.id];
+ if (!Object.keys(this.outNeighborsIndex[edge.source][edge.target]).length)
+ delete this.outNeighborsIndex[edge.source][edge.target];
+
+ delete this.allNeighborsIndex[edge.source][edge.target][edge.id];
+ if (!Object.keys(this.allNeighborsIndex[edge.source][edge.target]).length)
+ delete this.allNeighborsIndex[edge.source][edge.target];
+
+ if (edge.target !== edge.source) {
+ delete this.allNeighborsIndex[edge.target][edge.source][edge.id];
+ if (!Object.keys(this.allNeighborsIndex[edge.target][edge.source]).length)
+ delete this.allNeighborsIndex[edge.target][edge.source];
+ }
+
+ this.inNeighborsCount[edge.target]--;
+ this.outNeighborsCount[edge.source]--;
+ this.allNeighborsCount[edge.source]--;
+ this.allNeighborsCount[edge.target]--;
+
+ return this;
+ });
+
+ /**
+ * This method destroys the current instance. It basically empties each index
+ * and methods attached to the graph.
+ */
+ graph.addMethod('kill', function() {
+ // Delete arrays:
+ this.nodesArray.length = 0;
+ this.edgesArray.length = 0;
+ delete this.nodesArray;
+ delete this.edgesArray;
+
+ // Delete indexes:
+ delete this.nodesIndex;
+ delete this.edgesIndex;
+ delete this.inNeighborsIndex;
+ delete this.outNeighborsIndex;
+ delete this.allNeighborsIndex;
+ delete this.inNeighborsCount;
+ delete this.outNeighborsCount;
+ delete this.allNeighborsCount;
+ });
+
+ /**
+ * This method empties the nodes and edges arrays, as well as the different
+ * indexes.
+ *
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('clear', function() {
+ this.nodesArray.length = 0;
+ this.edgesArray.length = 0;
+
+ // Due to GC issues, I prefer not to create new object. These objects are
+ // only available from the methods and attached functions, but still, it is
+ // better to prevent ghost references to unrelevant data...
+ __emptyObject(this.nodesIndex);
+ __emptyObject(this.edgesIndex);
+ __emptyObject(this.nodesIndex);
+ __emptyObject(this.inNeighborsIndex);
+ __emptyObject(this.outNeighborsIndex);
+ __emptyObject(this.allNeighborsIndex);
+ __emptyObject(this.inNeighborsCount);
+ __emptyObject(this.outNeighborsCount);
+ __emptyObject(this.allNeighborsCount);
+
+ return this;
+ });
+
+ /**
+ * This method reads an object and adds the nodes and edges, through the
+ * proper methods "addNode" and "addEdge".
+ *
+ * Here is an example:
+ *
+ * > var myGraph = new graph();
+ * > myGraph.read({
+ * > nodes: [
+ * > { id: 'n0' },
+ * > { id: 'n1' }
+ * > ],
+ * > edges: [
+ * > {
+ * > id: 'e0',
+ * > source: 'n0',
+ * > target: 'n1'
+ * > }
+ * > ]
+ * > });
+ * >
+ * > console.log(
+ * > myGraph.nodes().length,
+ * > myGraph.edges().length
+ * > ); // outputs 2 1
+ *
+ * @param {object} g The graph object.
+ * @return {object} The graph instance.
+ */
+ graph.addMethod('read', function(g) {
+ var i,
+ a,
+ l;
+
+ a = g.nodes || [];
+ for (i = 0, l = a.length; i < l; i++)
+ this.addNode(a[i]);
+
+ a = g.edges || [];
+ for (i = 0, l = a.length; i < l; i++)
+ this.addEdge(a[i]);
+
+ return this;
+ });
+
+ /**
+ * This methods returns one or several nodes, depending on how it is called.
+ *
+ * To get the array of nodes, call "nodes" without argument. To get a
+ * specific node, call it with the id of the node. The get multiple node,
+ * call it with an array of ids, and it will return the array of nodes, in
+ * the same order.
+ *
+ * @param {?(string|array)} v Eventually one id, an array of ids.
+ * @return {object|array} The related node or array of nodes.
+ */
+ graph.addMethod('nodes', function(v) {
+ // Clone the array of nodes and return it:
+ if (!arguments.length)
+ return this.nodesArray.slice(0);
+
+ // Return the related node:
+ if (arguments.length === 1 &&
+ (typeof v === 'string' || typeof v === 'number'))
+ return this.nodesIndex[v];
+
+ // Return an array of the related node:
+ if (
+ arguments.length === 1 &&
+ Object.prototype.toString.call(v) === '[object Array]'
+ ) {
+ var i,
+ l,
+ a = [];
+
+ for (i = 0, l = v.length; i < l; i++)
+ if (typeof v[i] === 'string' || typeof v[i] === 'number')
+ a.push(this.nodesIndex[v[i]]);
+ else
+ throw 'nodes: Wrong arguments.';
+
+ return a;
+ }
+
+ throw 'nodes: Wrong arguments.';
+ });
+
+ /**
+ * This methods returns the degree of one or several nodes, depending on how
+ * it is called. It is also possible to get incoming or outcoming degrees
+ * instead by specifying 'in' or 'out' as a second argument.
+ *
+ * @param {string|array} v One id, an array of ids.
+ * @param {?string} which Which degree is required. Values are 'in',
+ * 'out', and by default the normal degree.
+ * @return {number|array} The related degree or array of degrees.
+ */
+ graph.addMethod('degree', function(v, which) {
+ // Check which degree is required:
+ which = {
+ 'in': this.inNeighborsCount,
+ 'out': this.outNeighborsCount
+ }[which || ''] || this.allNeighborsCount;
+
+ // Return the related node:
+ if (typeof v === 'string' || typeof v === 'number')
+ return which[v];
+
+ // Return an array of the related node:
+ if (Object.prototype.toString.call(v) === '[object Array]') {
+ var i,
+ l,
+ a = [];
+
+ for (i = 0, l = v.length; i < l; i++)
+ if (typeof v[i] === 'string' || typeof v[i] === 'number')
+ a.push(which[v[i]]);
+ else
+ throw 'degree: Wrong arguments.';
+
+ return a;
+ }
+
+ throw 'degree: Wrong arguments.';
+ });
+
+ /**
+ * This methods returns one or several edges, depending on how it is called.
+ *
+ * To get the array of edges, call "edges" without argument. To get a
+ * specific edge, call it with the id of the edge. The get multiple edge,
+ * call it with an array of ids, and it will return the array of edges, in
+ * the same order.
+ *
+ * @param {?(string|array)} v Eventually one id, an array of ids.
+ * @return {object|array} The related edge or array of edges.
+ */
+ graph.addMethod('edges', function(v) {
+ // Clone the array of edges and return it:
+ if (!arguments.length)
+ return this.edgesArray.slice(0);
+
+ // Return the related edge:
+ if (arguments.length === 1 &&
+ (typeof v === 'string' || typeof v === 'number'))
+ return this.edgesIndex[v];
+
+ // Return an array of the related edge:
+ if (
+ arguments.length === 1 &&
+ Object.prototype.toString.call(v) === '[object Array]'
+ ) {
+ var i,
+ l,
+ a = [];
+
+ for (i = 0, l = v.length; i < l; i++)
+ if (typeof v[i] === 'string' || typeof v[i] === 'number')
+ a.push(this.edgesIndex[v[i]]);
+ else
+ throw 'edges: Wrong arguments.';
+
+ return a;
+ }
+
+ throw 'edges: Wrong arguments.';
+ });
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof sigma !== 'undefined') {
+ sigma.classes = sigma.classes || Object.create(null);
+ sigma.classes.graph = graph;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = graph;
+ exports.graph = graph;
+ } else
+ this.graph = graph;
+}).call(this);
diff --git a/blogContent/projects/steam/src/classes/sigma.classes.quad.js b/blogContent/projects/steam/src/classes/sigma.classes.quad.js
new file mode 100644
index 0000000..fb11386
--- /dev/null
+++ b/blogContent/projects/steam/src/classes/sigma.classes.quad.js
@@ -0,0 +1,674 @@
+;(function(undefined) {
+ 'use strict';
+
+ /**
+ * Sigma Quadtree Module
+ * =====================
+ *
+ * Author: Guillaume Plique (Yomguithereal)
+ * Version: 0.2
+ */
+
+
+
+ /**
+ * Quad Geometric Operations
+ * -------------------------
+ *
+ * A useful batch of geometric operations used by the quadtree.
+ */
+
+ var _geom = {
+
+ /**
+ * Transforms a graph node with x, y and size into an
+ * axis-aligned square.
+ *
+ * @param {object} A graph node with at least a point (x, y) and a size.
+ * @return {object} A square: two points (x1, y1), (x2, y2) and height.
+ */
+ pointToSquare: function(n) {
+ return {
+ x1: n.x - n.size,
+ y1: n.y - n.size,
+ x2: n.x + n.size,
+ y2: n.y - n.size,
+ height: n.size * 2
+ };
+ },
+
+ /**
+ * Checks whether a rectangle is axis-aligned.
+ *
+ * @param {object} A rectangle defined by two points
+ * (x1, y1) and (x2, y2).
+ * @return {boolean} True if the rectangle is axis-aligned.
+ */
+ isAxisAligned: function(r) {
+ return r.x1 === r.x2 || r.y1 === r.y2;
+ },
+
+ /**
+ * Compute top points of an axis-aligned rectangle. This is useful in
+ * cases when the rectangle has been rotated (left, right or bottom up) and
+ * later operations need to know the top points.
+ *
+ * @param {object} An axis-aligned rectangle defined by two points
+ * (x1, y1), (x2, y2) and height.
+ * @return {object} A rectangle: two points (x1, y1), (x2, y2) and height.
+ */
+ axisAlignedTopPoints: function(r) {
+
+ // Basic
+ if (r.y1 === r.y2 && r.x1 < r.x2)
+ return r;
+
+ // Rotated to right
+ if (r.x1 === r.x2 && r.y2 > r.y1)
+ return {
+ x1: r.x1 - r.height, y1: r.y1,
+ x2: r.x1, y2: r.y1,
+ height: r.height
+ };
+
+ // Rotated to left
+ if (r.x1 === r.x2 && r.y2 < r.y1)
+ return {
+ x1: r.x1, y1: r.y2,
+ x2: r.x2 + r.height, y2: r.y2,
+ height: r.height
+ };
+
+ // Bottom's up
+ return {
+ x1: r.x2, y1: r.y1 - r.height,
+ x2: r.x1, y2: r.y1 - r.height,
+ height: r.height
+ };
+ },
+
+ /**
+ * Get coordinates of a rectangle's lower left corner from its top points.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @return {object} Coordinates of the corner (x, y).
+ */
+ lowerLeftCoor: function(r) {
+ var width = (
+ Math.sqrt(
+ Math.pow(r.x2 - r.x1, 2) +
+ Math.pow(r.y2 - r.y1, 2)
+ )
+ );
+
+ return {
+ x: r.x1 - (r.y2 - r.y1) * r.height / width,
+ y: r.y1 + (r.x2 - r.x1) * r.height / width
+ };
+ },
+
+ /**
+ * Get coordinates of a rectangle's lower right corner from its top points
+ * and its lower left corner.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @param {object} A corner's coordinates (x, y).
+ * @return {object} Coordinates of the corner (x, y).
+ */
+ lowerRightCoor: function(r, llc) {
+ return {
+ x: llc.x - r.x1 + r.x2,
+ y: llc.y - r.y1 + r.y2
+ };
+ },
+
+ /**
+ * Get the coordinates of all the corners of a rectangle from its top point.
+ *
+ * @param {object} A rectangle defined by two points (x1, y1) and (x2, y2).
+ * @return {array} An array of the four corners' coordinates (x, y).
+ */
+ rectangleCorners: function(r) {
+ var llc = this.lowerLeftCoor(r),
+ lrc = this.lowerRightCoor(r, llc);
+
+ return [
+ {x: r.x1, y: r.y1},
+ {x: r.x2, y: r.y2},
+ {x: llc.x, y: llc.y},
+ {x: lrc.x, y: lrc.y}
+ ];
+ },
+
+ /**
+ * Split a square defined by its boundaries into four.
+ *
+ * @param {object} Boundaries of the square (x, y, width, height).
+ * @return {array} An array containing the four new squares, themselves
+ * defined by an array of their four corners (x, y).
+ */
+ splitSquare: function(b) {
+ return [
+ [
+ {x: b.x, y: b.y},
+ {x: b.x + b.width / 2, y: b.y},
+ {x: b.x, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2}
+ ],
+ [
+ {x: b.x + b.width / 2, y: b.y},
+ {x: b.x + b.width, y: b.y},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x + b.width, y: b.y + b.height / 2}
+ ],
+ [
+ {x: b.x, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x, y: b.y + b.height},
+ {x: b.x + b.width / 2, y: b.y + b.height}
+ ],
+ [
+ {x: b.x + b.width / 2, y: b.y + b.height / 2},
+ {x: b.x + b.width, y: b.y + b.height / 2},
+ {x: b.x + b.width / 2, y: b.y + b.height},
+ {x: b.x + b.width, y: b.y + b.height}
+ ]
+ ];
+ },
+
+ /**
+ * Compute the four axis between corners of rectangle A and corners of
+ * rectangle B. This is needed later to check an eventual collision.
+ *
+ * @param {array} An array of rectangle A's four corners (x, y).
+ * @param {array} An array of rectangle B's four corners (x, y).
+ * @return {array} An array of four axis defined by their coordinates (x,y).
+ */
+ axis: function(c1, c2) {
+ return [
+ {x: c1[1].x - c1[0].x, y: c1[1].y - c1[0].y},
+ {x: c1[1].x - c1[3].x, y: c1[1].y - c1[3].y},
+ {x: c2[0].x - c2[2].x, y: c2[0].y - c2[2].y},
+ {x: c2[0].x - c2[1].x, y: c2[0].y - c2[1].y}
+ ];
+ },
+
+ /**
+ * Project a rectangle's corner on an axis.
+ *
+ * @param {object} Coordinates of a corner (x, y).
+ * @param {object} Coordinates of an axis (x, y).
+ * @return {object} The projection defined by coordinates (x, y).
+ */
+ projection: function(c, a) {
+ var l = (
+ (c.x * a.x + c.y * a.y) /
+ (Math.pow(a.x, 2) + Math.pow(a.y, 2))
+ );
+
+ return {
+ x: l * a.x,
+ y: l * a.y
+ };
+ },
+
+ /**
+ * Check whether two rectangles collide on one particular axis.
+ *
+ * @param {object} An axis' coordinates (x, y).
+ * @param {array} Rectangle A's corners.
+ * @param {array} Rectangle B's corners.
+ * @return {boolean} True if the rectangles collide on the axis.
+ */
+ axisCollision: function(a, c1, c2) {
+ var sc1 = [],
+ sc2 = [];
+
+ for (var ci = 0; ci < 4; ci++) {
+ var p1 = this.projection(c1[ci], a),
+ p2 = this.projection(c2[ci], a);
+
+ sc1.push(p1.x * a.x + p1.y * a.y);
+ sc2.push(p2.x * a.x + p2.y * a.y);
+ }
+
+ var maxc1 = Math.max.apply(Math, sc1),
+ maxc2 = Math.max.apply(Math, sc2),
+ minc1 = Math.min.apply(Math, sc1),
+ minc2 = Math.min.apply(Math, sc2);
+
+ return (minc2 <= maxc1 && maxc2 >= minc1);
+ },
+
+ /**
+ * Check whether two rectangles collide on each one of their four axis. If
+ * all axis collide, then the two rectangles do collide on the plane.
+ *
+ * @param {array} Rectangle A's corners.
+ * @param {array} Rectangle B's corners.
+ * @return {boolean} True if the rectangles collide.
+ */
+ collision: function(c1, c2) {
+ var axis = this.axis(c1, c2),
+ col = true;
+
+ for (var i = 0; i < 4; i++)
+ col = col && this.axisCollision(axis[i], c1, c2);
+
+ return col;
+ }
+ };
+
+
+ /**
+ * Quad Functions
+ * ------------
+ *
+ * The Quadtree functions themselves.
+ * For each of those functions, we consider that in a splitted quad, the
+ * index of each node is the following:
+ * 0: top left
+ * 1: top right
+ * 2: bottom left
+ * 3: bottom right
+ *
+ * Moreover, the hereafter quad's philosophy is to consider that if an element
+ * collides with more than one nodes, this element belongs to each of the
+ * nodes it collides with where other would let it lie on a higher node.
+ */
+
+ /**
+ * Get the index of the node containing the point in the quad
+ *
+ * @param {object} point A point defined by coordinates (x, y).
+ * @param {object} quadBounds Boundaries of the quad (x, y, width, heigth).
+ * @return {integer} The index of the node containing the point.
+ */
+ function _quadIndex(point, quadBounds) {
+ var xmp = quadBounds.x + quadBounds.width / 2,
+ ymp = quadBounds.y + quadBounds.height / 2,
+ top = (point.y < ymp),
+ left = (point.x < xmp);
+
+ if (top) {
+ if (left)
+ return 0;
+ else
+ return 1;
+ }
+ else {
+ if (left)
+ return 2;
+ else
+ return 3;
+ }
+ }
+
+ /**
+ * Get a list of indexes of nodes containing an axis-aligned rectangle
+ *
+ * @param {object} rectangle A rectangle defined by two points (x1, y1),
+ * (x2, y2) and height.
+ * @param {array} quadCorners An array of the quad nodes' corners.
+ * @return {array} An array of indexes containing one to
+ * four integers.
+ */
+ function _quadIndexes(rectangle, quadCorners) {
+ var indexes = [];
+
+ // Iterating through quads
+ for (var i = 0; i < 4; i++)
+ if ((rectangle.x2 >= quadCorners[i][0].x) &&
+ (rectangle.x1 <= quadCorners[i][1].x) &&
+ (rectangle.y1 + rectangle.height >= quadCorners[i][0].y) &&
+ (rectangle.y1 <= quadCorners[i][2].y))
+ indexes.push(i);
+
+ return indexes;
+ }
+
+ /**
+ * Get a list of indexes of nodes containing a non-axis-aligned rectangle
+ *
+ * @param {array} corners An array containing each corner of the
+ * rectangle defined by its coordinates (x, y).
+ * @param {array} quadCorners An array of the quad nodes' corners.
+ * @return {array} An array of indexes containing one to
+ * four integers.
+ */
+ function _quadCollision(corners, quadCorners) {
+ var indexes = [];
+
+ // Iterating through quads
+ for (var i = 0; i < 4; i++)
+ if (_geom.collision(corners, quadCorners[i]))
+ indexes.push(i);
+
+ return indexes;
+ }
+
+ /**
+ * Subdivide a quad by creating a node at a precise index. The function does
+ * not generate all four nodes not to potentially create unused nodes.
+ *
+ * @param {integer} index The index of the node to create.
+ * @param {object} quad The quad object to subdivide.
+ * @return {object} A new quad representing the node created.
+ */
+ function _quadSubdivide(index, quad) {
+ var next = quad.level + 1,
+ subw = Math.round(quad.bounds.width / 2),
+ subh = Math.round(quad.bounds.height / 2),
+ qx = Math.round(quad.bounds.x),
+ qy = Math.round(quad.bounds.y),
+ x,
+ y;
+
+ switch (index) {
+ case 0:
+ x = qx;
+ y = qy;
+ break;
+ case 1:
+ x = qx + subw;
+ y = qy;
+ break;
+ case 2:
+ x = qx;
+ y = qy + subh;
+ break;
+ case 3:
+ x = qx + subw;
+ y = qy + subh;
+ break;
+ }
+
+ return _quadTree(
+ {x: x, y: y, width: subw, height: subh},
+ next,
+ quad.maxElements,
+ quad.maxLevel
+ );
+ }
+
+ /**
+ * Recursively insert an element into the quadtree. Only points
+ * with size, i.e. axis-aligned squares, may be inserted with this
+ * method.
+ *
+ * @param {object} el The element to insert in the quadtree.
+ * @param {object} sizedPoint A sized point defined by two top points
+ * (x1, y1), (x2, y2) and height.
+ * @param {object} quad The quad in which to insert the element.
+ * @return {undefined} The function does not return anything.
+ */
+ function _quadInsert(el, sizedPoint, quad) {
+ if (quad.level < quad.maxLevel) {
+
+ // Searching appropriate quads
+ var indexes = _quadIndexes(sizedPoint, quad.corners);
+
+ // Iterating
+ for (var i = 0, l = indexes.length; i < l; i++) {
+
+ // Subdividing if necessary
+ if (quad.nodes[indexes[i]] === undefined)
+ quad.nodes[indexes[i]] = _quadSubdivide(indexes[i], quad);
+
+ // Recursion
+ _quadInsert(el, sizedPoint, quad.nodes[indexes[i]]);
+ }
+ }
+ else {
+
+ // Pushing the element in a leaf node
+ quad.elements.push(el);
+ }
+ }
+
+ /**
+ * Recursively retrieve every elements held by the node containing the
+ * searched point.
+ *
+ * @param {object} point The searched point (x, y).
+ * @param {object} quad The searched quad.
+ * @return {array} An array of elements contained in the relevant
+ * node.
+ */
+ function _quadRetrievePoint(point, quad) {
+ if (quad.level < quad.maxLevel) {
+ var index = _quadIndex(point, quad.bounds);
+
+ // If node does not exist we return an empty list
+ if (quad.nodes[index] !== undefined) {
+ return _quadRetrievePoint(point, quad.nodes[index]);
+ }
+ else {
+ return [];
+ }
+ }
+ else {
+ return quad.elements;
+ }
+ }
+
+ /**
+ * Recursively retrieve every elements contained within an rectangular area
+ * that may or may not be axis-aligned.
+ *
+ * @param {object|array} rectData The searched area defined either by
+ * an array of four corners (x, y) in
+ * the case of a non-axis-aligned
+ * rectangle or an object with two top
+ * points (x1, y1), (x2, y2) and height.
+ * @param {object} quad The searched quad.
+ * @param {function} collisionFunc The collision function used to search
+ * for node indexes.
+ * @param {array?} els The retrieved elements.
+ * @return {array} An array of elements contained in the
+ * area.
+ */
+ function _quadRetrieveArea(rectData, quad, collisionFunc, els) {
+ els = els || {};
+
+ if (quad.level < quad.maxLevel) {
+ var indexes = collisionFunc(rectData, quad.corners);
+
+ for (var i = 0, l = indexes.length; i < l; i++)
+ if (quad.nodes[indexes[i]] !== undefined)
+ _quadRetrieveArea(
+ rectData,
+ quad.nodes[indexes[i]],
+ collisionFunc,
+ els
+ );
+ } else
+ for (var j = 0, m = quad.elements.length; j < m; j++)
+ if (els[quad.elements[j].id] === undefined)
+ els[quad.elements[j].id] = quad.elements[j];
+
+ return els;
+ }
+
+ /**
+ * Creates the quadtree object itself.
+ *
+ * @param {object} bounds The boundaries of the quad defined by an
+ * origin (x, y), width and heigth.
+ * @param {integer} level The level of the quad in the tree.
+ * @param {integer} maxElements The max number of element in a leaf node.
+ * @param {integer} maxLevel The max recursion level of the tree.
+ * @return {object} The quadtree object.
+ */
+ function _quadTree(bounds, level, maxElements, maxLevel) {
+ return {
+ level: level || 0,
+ bounds: bounds,
+ corners: _geom.splitSquare(bounds),
+ maxElements: maxElements || 20,
+ maxLevel: maxLevel || 4,
+ elements: [],
+ nodes: []
+ };
+ }
+
+
+ /**
+ * Sigma Quad Constructor
+ * ----------------------
+ *
+ * The quad API as exposed to sigma.
+ */
+
+ /**
+ * The quad core that will become the sigma interface with the quadtree.
+ *
+ * property {object} _tree Property holding the quadtree object.
+ * property {object} _geom Exposition of the _geom namespace for testing.
+ * property {object} _cache Cache for the area method.
+ */
+ var quad = function() {
+ this._geom = _geom;
+ this._tree = null;
+ this._cache = {
+ query: false,
+ result: false
+ };
+ };
+
+ /**
+ * Index a graph by inserting its nodes into the quadtree.
+ *
+ * @param {array} nodes An array of nodes to index.
+ * @param {object} params An object of parameters with at least the quad
+ * bounds.
+ * @return {object} The quadtree object.
+ *
+ * Parameters:
+ * ----------
+ * bounds: {object} boundaries of the quad defined by its origin (x, y)
+ * width and heigth.
+ * prefix: {string?} a prefix for node geometric attributes.
+ * maxElements: {integer?} the max number of elements in a leaf node.
+ * maxLevel: {integer?} the max recursion level of the tree.
+ */
+ quad.prototype.index = function(nodes, params) {
+
+ // Enforcing presence of boundaries
+ if (!params.bounds)
+ throw 'sigma.classes.quad.index: bounds information not given.';
+
+ // Prefix
+ var prefix = params.prefix || '';
+
+ // Building the tree
+ this._tree = _quadTree(
+ params.bounds,
+ 0,
+ params.maxElements,
+ params.maxLevel
+ );
+
+ // Inserting graph nodes into the tree
+ for (var i = 0, l = nodes.length; i < l; i++) {
+
+ // Inserting node
+ _quadInsert(
+ nodes[i],
+ _geom.pointToSquare({
+ x: nodes[i][prefix + 'x'],
+ y: nodes[i][prefix + 'y'],
+ size: nodes[i][prefix + 'size']
+ }),
+ this._tree
+ );
+ }
+
+ // Reset cache:
+ this._cache = {
+ query: false,
+ result: false
+ };
+
+ // remove?
+ return this._tree;
+ };
+
+ /**
+ * Retrieve every graph nodes held by the quadtree node containing the
+ * searched point.
+ *
+ * @param {number} x of the point.
+ * @param {number} y of the point.
+ * @return {array} An array of nodes retrieved.
+ */
+ quad.prototype.point = function(x, y) {
+ return this._tree ?
+ _quadRetrievePoint({x: x, y: y}, this._tree) || [] :
+ [];
+ };
+
+ /**
+ * Retrieve every graph nodes within a rectangular area. The methods keep the
+ * last area queried in cache for optimization reason and will act differently
+ * for the same reason if the area is axis-aligned or not.
+ *
+ * @param {object} A rectangle defined by two top points (x1, y1), (x2, y2)
+ * and height.
+ * @return {array} An array of nodes retrieved.
+ */
+ quad.prototype.area = function(rect) {
+ var serialized = JSON.stringify(rect),
+ collisionFunc,
+ rectData;
+
+ // Returning cache?
+ if (this._cache.query === serialized)
+ return this._cache.result;
+
+ // Axis aligned ?
+ if (_geom.isAxisAligned(rect)) {
+ collisionFunc = _quadIndexes;
+ rectData = _geom.axisAlignedTopPoints(rect);
+ }
+ else {
+ collisionFunc = _quadCollision;
+ rectData = _geom.rectangleCorners(rect);
+ }
+
+ // Retrieving nodes
+ var nodes = this._tree ?
+ _quadRetrieveArea(
+ rectData,
+ this._tree,
+ collisionFunc
+ ) :
+ [];
+
+ // Object to array
+ var nodesArray = [];
+ for (var i in nodes)
+ nodesArray.push(nodes[i]);
+
+ // Caching
+ this._cache.query = serialized;
+ this._cache.result = nodesArray;
+
+ return nodesArray;
+ };
+
+
+ /**
+ * EXPORT:
+ * *******
+ */
+ if (typeof this.sigma !== 'undefined') {
+ this.sigma.classes = this.sigma.classes || {};
+ this.sigma.classes.quad = quad;
+ } else if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = quad;
+ exports.quad = quad;
+ } else
+ this.quad = quad;
+}).call(this);
diff --git a/blogContent/projects/steam/src/conrad.js b/blogContent/projects/steam/src/conrad.js
new file mode 100644
index 0000000..bdb6610
--- /dev/null
+++ b/blogContent/projects/steam/src/conrad.js
@@ -0,0 +1,984 @@
+/**
+ * conrad.js is a tiny JavaScript jobs scheduler,
+ *
+ * Version: 0.1.0
+ * Sources: http://github.com/jacomyal/conrad.js
+ * Doc: http://github.com/jacomyal/conrad.js#readme
+ *
+ * License:
+ * --------
+ * Copyright © 2013 Alexis Jacomy, Sciences-Po médialab
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * The Software is provided "as is", without warranty of any kind, express or
+ * implied, including but not limited to the warranties of merchantability,
+ * fitness for a particular purpose and noninfringement. In no event shall the
+ * authors or copyright holders be liable for any claim, damages or other
+ * liability, whether in an action of contract, tort or otherwise, arising
+ * from, out of or in connection with the software or the use or other dealings
+ * in the Software.
+ */
+(function(global) {
+ 'use strict';
+
+ // Check that conrad.js has not been loaded yet:
+ if (global.conrad)
+ throw new Error('conrad already exists');
+
+
+ /**
+ * PRIVATE VARIABLES:
+ * ******************
+ */
+
+ /**
+ * A flag indicating whether conrad is running or not.
+ *
+ * @type {Number}
+ */
+ var _lastFrameTime;
+
+ /**
+ * A flag indicating whether conrad is running or not.
+ *
+ * @type {Boolean}
+ */
+ var _isRunning = false;
+
+ /**
+ * The hash of registered jobs. Each job must at least have a unique ID
+ * under the key "id" and a function under the key "job". This hash
+ * contains each running job and each waiting job.
+ *
+ * @type {Object}
+ */
+ var _jobs = {};
+
+ /**
+ * The hash of currently running jobs.
+ *
+ * @type {Object}
+ */
+ var _runningJobs = {};
+
+ /**
+ * The array of currently running jobs, sorted by priority.
+ *
+ * @type {Array}
+ */
+ var _sortedByPriorityJobs = [];
+
+ /**
+ * The array of currently waiting jobs.
+ *
+ * @type {Object}
+ */
+ var _waitingJobs = {};
+
+ /**
+ * The array of finished jobs. They are stored in an array, since two jobs
+ * with the same "id" can happen at two different times.
+ *
+ * @type {Array}
+ */
+ var _doneJobs = [];
+
+ /**
+ * A dirty flag to keep conrad from starting: Indeed, when addJob() is called
+ * with several jobs, conrad must be started only at the end. This flag keeps
+ * me from duplicating the code that effectively adds a job.
+ *
+ * @type {Boolean}
+ */
+ var _noStart = false;
+
+ /**
+ * An hash containing some global settings about how conrad.js should
+ * behave.
+ *
+ * @type {Object}
+ */
+ var _parameters = {
+ frameDuration: 20,
+ history: true
+ };
+
+ /**
+ * This object contains every handlers bound to conrad events. It does not
+ * requirea any DOM implementation, since the events are all JavaScript.
+ *
+ * @type {Object}
+ */
+ var _handlers = Object.create(null);
+
+
+ /**
+ * PRIVATE FUNCTIONS:
+ * ******************
+ */
+
+ /**
+ * Will execute the handler everytime that the indicated event (or the
+ * indicated events) will be triggered.
+ *
+ * @param {string|array|object} events The name of the event (or the events
+ * separated by spaces).
+ * @param {function(Object)} handler The handler to bind.
+ * @return {Object} Returns conrad.
+ */
+ function _bind(events, handler) {
+ var i,
+ i_end,
+ event,
+ eArray;
+
+ if (!arguments.length)
+ return;
+ else if (
+ arguments.length === 1 &&
+ Object(arguments[0]) === arguments[0]
+ )
+ for (events in arguments[0])
+ _bind(events, arguments[0][events]);
+ else if (arguments.length > 1) {
+ eArray =
+ Array.isArray(events) ?
+ events :
+ events.split(/ /);
+
+ for (i = 0, i_end = eArray.length; i !== i_end; i += 1) {
+ event = eArray[i];
+
+ if (!_handlers[event])
+ _handlers[event] = [];
+
+ // Using an object instead of directly the handler will make possible
+ // later to add flags
+ _handlers[event].push({
+ handler: handler
+ });
+ }
+ }
+ }
+
+ /**
+ * Removes the handler from a specified event (or specified events).
+ *
+ * @param {?string} events The name of the event (or the events
+ * separated by spaces). If undefined,
+ * then all handlers are removed.
+ * @param {?function(Object)} handler The handler to unbind. If undefined,
+ * each handler bound to the event or the
+ * events will be removed.
+ * @return {Object} Returns conrad.
+ */
+ function _unbind(events, handler) {
+ var i,
+ i_end,
+ j,
+ j_end,
+ a,
+ event,
+ eArray = Array.isArray(events) ?
+ events :
+ events.split(/ /);
+
+ if (!arguments.length)
+ _handlers = Object.create(null);
+ else if (handler) {
+ for (i = 0, i_end = eArray.length; i !== i_end; i += 1) {
+ event = eArray[i];
+ if (_handlers[event]) {
+ a = [];
+ for (j = 0, j_end = _handlers[event].length; j !== j_end; j += 1)
+ if (_handlers[event][j].handler !== handler)
+ a.push(_handlers[event][j]);
+
+ _handlers[event] = a;
+ }
+
+ if (_handlers[event] && _handlers[event].length === 0)
+ delete _handlers[event];
+ }
+ } else
+ for (i = 0, i_end = eArray.length; i !== i_end; i += 1)
+ delete _handlers[eArray[i]];
+ }
+
+ /**
+ * Executes each handler bound to the event.
+ *
+ * @param {string} events The name of the event (or the events separated
+ * by spaces).
+ * @param {?Object} data The content of the event (optional).
+ * @return {Object} Returns conrad.
+ */
+ function _dispatch(events, data) {
+ var i,
+ j,
+ i_end,
+ j_end,
+ event,
+ eventName,
+ eArray = Array.isArray(events) ?
+ events :
+ events.split(/ /);
+
+ data = data === undefined ? {} : data;
+
+ for (i = 0, i_end = eArray.length; i !== i_end; i += 1) {
+ eventName = eArray[i];
+
+ if (_handlers[eventName]) {
+ event = {
+ type: eventName,
+ data: data || {}
+ };
+
+ for (j = 0, j_end = _handlers[eventName].length; j !== j_end; j += 1)
+ try {
+ _handlers[eventName][j].handler(event);
+ } catch (e) {}
+ }
+ }
+ }
+
+ /**
+ * Executes the most prioritary job once, and deals with filling the stats
+ * (done, time, averageTime, currentTime, etc...).
+ *
+ * @return {?Object} Returns the job object if it has to be killed, null else.
+ */
+ function _executeFirstJob() {
+ var i,
+ l,
+ test,
+ kill,
+ pushed = false,
+ time = __dateNow(),
+ job = _sortedByPriorityJobs.shift();
+
+ // Execute the job and look at the result:
+ test = job.job();
+
+ // Deal with stats:
+ time = __dateNow() - time;
+ job.done++;
+ job.time += time;
+ job.currentTime += time;
+ job.weightTime = job.currentTime / (job.weight || 1);
+ job.averageTime = job.time / job.done;
+
+ // Check if the job has to be killed:
+ kill = job.count ? (job.count <= job.done) : !test;
+
+ // Reset priorities:
+ if (!kill) {
+ for (i = 0, l = _sortedByPriorityJobs.length; i < l; i++)
+ if (_sortedByPriorityJobs[i].weightTime > job.weightTime) {
+ _sortedByPriorityJobs.splice(i, 0, job);
+ pushed = true;
+ break;
+ }
+
+ if (!pushed)
+ _sortedByPriorityJobs.push(job);
+ }
+
+ return kill ? job : null;
+ }
+
+ /**
+ * Activates a job, by adding it to the _runningJobs object and the
+ * _sortedByPriorityJobs array. It also initializes its currentTime value.
+ *
+ * @param {Object} job The job to activate.
+ */
+ function _activateJob(job) {
+ var l = _sortedByPriorityJobs.length;
+
+ // Add the job to the running jobs:
+ _runningJobs[job.id] = job;
+ job.status = 'running';
+
+ // Add the job to the priorities:
+ if (l) {
+ job.weightTime = _sortedByPriorityJobs[l - 1].weightTime;
+ job.currentTime = job.weightTime * (job.weight || 1);
+ }
+
+ // Initialize the job and dispatch:
+ job.startTime = __dateNow();
+ _dispatch('jobStarted', __clone(job));
+
+ _sortedByPriorityJobs.push(job);
+ }
+
+ /**
+ * The main loop of conrad.js:
+ * . It executes job such that they all occupate the same processing time.
+ * . It stops jobs that do not need to be executed anymore.
+ * . It triggers callbacks when it is relevant.
+ * . It starts waiting jobs when they need to be started.
+ * . It injects frames to keep a constant frapes per second ratio.
+ * . It stops itself when there are no more jobs to execute.
+ */
+ function _loop() {
+ var k,
+ o,
+ l,
+ job,
+ time,
+ deadJob;
+
+ // Deal with the newly added jobs (the _jobs object):
+ for (k in _jobs) {
+ job = _jobs[k];
+
+ if (job.after)
+ _waitingJobs[k] = job;
+ else
+ _activateJob(job);
+
+ delete _jobs[k];
+ }
+
+ // Set the _isRunning flag to false if there are no running job:
+ _isRunning = !!_sortedByPriorityJobs.length;
+
+ // Deal with the running jobs (the _runningJobs object):
+ while (
+ _sortedByPriorityJobs.length &&
+ __dateNow() - _lastFrameTime < _parameters.frameDuration
+ ) {
+ deadJob = _executeFirstJob();
+
+ // Deal with the case where the job has ended:
+ if (deadJob) {
+ _killJob(deadJob.id);
+
+ // Check for waiting jobs:
+ for (k in _waitingJobs)
+ if (_waitingJobs[k].after === deadJob.id) {
+ _activateJob(_waitingJobs[k]);
+ delete _waitingJobs[k];
+ }
+ }
+ }
+
+ // Check if conrad still has jobs to deal with, and kill it if not:
+ if (_isRunning) {
+ // Update the _lastFrameTime:
+ _lastFrameTime = __dateNow();
+
+ _dispatch('enterFrame');
+ setTimeout(_loop, 0);
+ } else
+ _dispatch('stop');
+ }
+
+ /**
+ * Adds one or more jobs, and starts the loop if no job was running before. A
+ * job is at least a unique string "id" and a function, and there are some
+ * parameters that you can specify for each job to modify the way conrad will
+ * execute it. If a job is added with the "id" of another job that is waiting
+ * or still running, an error will be thrown.
+ *
+ * When a job is added, it is referenced in the _jobs object, by its id.
+ * Then, if it has to be executed right now, it will be also referenced in
+ * the _runningJobs object. If it has to wait, then it will be added into the
+ * _waitingJobs object, until it can start.
+ *
+ * Keep reading this documentation to see how to call this method.
+ *
+ * @return {Object} Returns conrad.
+ *
+ * Adding one job:
+ * ***************
+ * Basically, a job is defined by its string id and a function (the job). It
+ * is also possible to add some parameters:
+ *
+ * > conrad.addJob('myJobId', myJobFunction);
+ * > conrad.addJob('myJobId', {
+ * > job: myJobFunction,
+ * > someParameter: someValue
+ * > });
+ * > conrad.addJob({
+ * > id: 'myJobId',
+ * > job: myJobFunction,
+ * > someParameter: someValue
+ * > });
+ *
+ * Adding several jobs:
+ * ********************
+ * When adding several jobs at the same time, it is possible to specify
+ * parameters for each one individually or for all:
+ *
+ * > conrad.addJob([
+ * > {
+ * > id: 'myJobId1',
+ * > job: myJobFunction1,
+ * > someParameter1: someValue1
+ * > },
+ * > {
+ * > id: 'myJobId2',
+ * > job: myJobFunction2,
+ * > someParameter2: someValue2
+ * > }
+ * > ], {
+ * > someCommonParameter: someCommonValue
+ * > });
+ * > conrad.addJob({
+ * > myJobId1: {,
+ * > job: myJobFunction1,
+ * > someParameter1: someValue1
+ * > },
+ * > myJobId2: {,
+ * > job: myJobFunction2,
+ * > someParameter2: someValue2
+ * > }
+ * > }, {
+ * > someCommonParameter: someCommonValue
+ * > });
+ * > conrad.addJob({
+ * > myJobId1: myJobFunction1,
+ * > myJobId2: myJobFunction2
+ * > }, {
+ * > someCommonParameter: someCommonValue
+ * > });
+ *
+ * Recognized parameters:
+ * **********************
+ * Here is the exhaustive list of every accepted parameters:
+ *
+ * {?Function} end A callback to execute when the job is ended. It is
+ * not executed if the job is killed instead of ended
+ * "naturally".
+ * {?Integer} count The number of time the job has to be executed.
+ * {?Number} weight If specified, the job will be executed as it was
+ * added "weight" times.
+ * {?String} after The id of another job (eventually not added yet).
+ * If specified, this job will start only when the
+ * specified "after" job is ended.
+ */
+ function _addJob(v1, v2) {
+ var i,
+ l,
+ o;
+
+ // Array of jobs:
+ if (Array.isArray(v1)) {
+ // Keep conrad to start until the last job is added:
+ _noStart = true;
+
+ for (i = 0, l = v1.length; i < l; i++)
+ _addJob(v1[i].id, __extend(v1[i], v2));
+
+ _noStart = false;
+ if (!_isRunning) {
+ // Update the _lastFrameTime:
+ _lastFrameTime = __dateNow();
+
+ _dispatch('start');
+ _loop();
+ }
+ } else if (typeof v1 === 'object') {
+ // One job (object):
+ if (typeof v1.id === 'string')
+ _addJob(v1.id, v1);
+
+ // Hash of jobs:
+ else {
+ // Keep conrad to start until the last job is added:
+ _noStart = true;
+
+ for (i in v1)
+ if (typeof v1[i] === 'function')
+ _addJob(i, __extend({
+ job: v1[i]
+ }, v2));
+ else
+ _addJob(i, __extend(v1[i], v2));
+
+ _noStart = false;
+ if (!_isRunning) {
+ // Update the _lastFrameTime:
+ _lastFrameTime = __dateNow();
+
+ _dispatch('start');
+ _loop();
+ }
+ }
+
+ // One job (string, *):
+ } else if (typeof v1 === 'string') {
+ if (_hasJob(v1))
+ throw new Error(
+ '[conrad.addJob] Job with id "' + v1 + '" already exists.'
+ );
+
+ // One job (string, function):
+ if (typeof v2 === 'function') {
+ o = {
+ id: v1,
+ done: 0,
+ time: 0,
+ status: 'waiting',
+ currentTime: 0,
+ averageTime: 0,
+ weightTime: 0,
+ job: v2
+ };
+
+ // One job (string, object):
+ } else if (typeof v2 === 'object') {
+ o = __extend(
+ {
+ id: v1,
+ done: 0,
+ time: 0,
+ status: 'waiting',
+ currentTime: 0,
+ averageTime: 0,
+ weightTime: 0
+ },
+ v2
+ );
+
+ // If none of those cases, throw an error:
+ } else
+ throw new Error('[conrad.addJob] Wrong arguments.');
+
+ // Effectively add the job:
+ _jobs[v1] = o;
+ _dispatch('jobAdded', __clone(o));
+
+ // Check if the loop has to be started:
+ if (!_isRunning && !_noStart) {
+ // Update the _lastFrameTime:
+ _lastFrameTime = __dateNow();
+
+ _dispatch('start');
+ _loop();
+ }
+
+ // If none of those cases, throw an error:
+ } else
+ throw new Error('[conrad.addJob] Wrong arguments.');
+
+ return this;
+ }
+
+ /**
+ * Kills one or more jobs, indicated by their ids. It is only possible to
+ * kill running jobs or waiting jobs. If you try to kill a job that does not
+ * exist or that is already killed, a warning will be thrown.
+ *
+ * @param {Array|String} v1 A string job id or an array of job ids.
+ * @return {Object} Returns conrad.
+ */
+ function _killJob(v1) {
+ var i,
+ l,
+ k,
+ a,
+ job,
+ found = false;
+
+ // Array of job ids:
+ if (Array.isArray(v1))
+ for (i = 0, l = v1.length; i < l; i++)
+ _killJob(v1[i]);
+
+ // One job's id:
+ else if (typeof v1 === 'string') {
+ a = [_runningJobs, _waitingJobs, _jobs];
+
+ // Remove the job from the hashes:
+ for (i = 0, l = a.length; i < l; i++)
+ if (v1 in a[i]) {
+ job = a[i][v1];
+
+ if (_parameters.history) {
+ job.status = 'done';
+ _doneJobs.push(job);
+ }
+
+ _dispatch('jobEnded', __clone(job));
+ delete a[i][v1];
+
+ if (typeof job.end === 'function')
+ job.end();
+
+ found = true;
+ }
+
+ // Remove the priorities array:
+ a = _sortedByPriorityJobs;
+ for (i = 0, l = a.length; i < l; i++)
+ if (a[i].id === v1) {
+ a.splice(i, 1);
+ break;
+ }
+
+ if (!found)
+ throw new Error('[conrad.killJob] Job "' + v1 + '" not found.');
+
+ // If none of those cases, throw an error:
+ } else
+ throw new Error('[conrad.killJob] Wrong arguments.');
+
+ return this;
+ }
+
+ /**
+ * Kills every running, waiting, and just added jobs.
+ *
+ * @return {Object} Returns conrad.
+ */
+ function _killAll() {
+ var k,
+ jobs = __extend(_jobs, _runningJobs, _waitingJobs);
+
+ // Take every jobs and push them into the _doneJobs object:
+ if (_parameters.history)
+ for (k in jobs) {
+ jobs[k].status = 'done';
+ _doneJobs.push(jobs[k]);
+
+ if (typeof jobs[k].end === 'function')
+ jobs[k].end();
+ }
+
+ // Reinitialize the different jobs lists:
+ _jobs = {};
+ _waitingJobs = {};
+ _runningJobs = {};
+ _sortedByPriorityJobs = [];
+
+ // In case some jobs are added right after the kill:
+ _isRunning = false;
+
+ return this;
+ }
+
+ /**
+ * Returns true if a job with the specified id is currently running or
+ * waiting, and false else.
+ *
+ * @param {String} id The id of the job.
+ * @return {?Object} Returns the job object if it exists.
+ */
+ function _hasJob(id) {
+ var job = _jobs[id] || _runningJobs[id] || _waitingJobs[id];
+ return job ? __extend(job) : null;
+ }
+
+ /**
+ * This method will set the setting specified by "v1" to the value specified
+ * by "v2" if both are given, and else return the current value of the
+ * settings "v1".
+ *
+ * @param {String} v1 The name of the property.
+ * @param {?*} v2 Eventually, a value to set to the specified
+ * property.
+ * @return {Object|*} Returns the specified settings value if "v2" is not
+ * given, and conrad else.
+ */
+ function _settings(v1, v2) {
+ var o;
+
+ if (typeof a1 === 'string' && arguments.length === 1)
+ return _parameters[a1];
+ else {
+ o = (typeof a1 === 'object' && arguments.length === 1) ?
+ a1 || {} :
+ {};
+ if (typeof a1 === 'string')
+ o[a1] = a2;
+
+ for (var k in o)
+ if (o[k] !== undefined)
+ _parameters[k] = o[k];
+ else
+ delete _parameters[k];
+
+ return this;
+ }
+ }
+
+ /**
+ * Returns true if conrad is currently running, and false else.
+ *
+ * @return {Boolean} Returns _isRunning.
+ */
+ function _getIsRunning() {
+ return _isRunning;
+ }
+
+ /**
+ * Unreference every job that is stored in the _doneJobs object. It will
+ * not be possible anymore to get stats about these jobs, but it will release
+ * the memory.
+ *
+ * @return {Object} Returns conrad.
+ */
+ function _clearHistory() {
+ _doneJobs = [];
+ return this;
+ }
+
+ /**
+ * Returns a snapshot of every data about jobs that wait to be started, are
+ * currently running or are done.
+ *
+ * It is possible to get only running, waiting or done jobs by giving
+ * "running", "waiting" or "done" as fist argument.
+ *
+ * It is also possible to get every job with a specified id by giving it as
+ * first argument. Also, using a RegExp instead of an id will return every
+ * jobs whose ids match the RegExp. And these two last use cases work as well
+ * by giving before "running", "waiting" or "done".
+ *
+ * @return {Array} The array of the matching jobs.
+ *
+ * Some call examples:
+ * *******************
+ * > conrad.getStats('running')
+ * > conrad.getStats('waiting')
+ * > conrad.getStats('done')
+ * > conrad.getStats('myJob')
+ * > conrad.getStats(/test/)
+ * > conrad.getStats('running', 'myRunningJob')
+ * > conrad.getStats('running', /test/)
+ */
+ function _getStats(v1, v2) {
+ var a,
+ k,
+ i,
+ l,
+ stats,
+ pattern,
+ isPatternString;
+
+ if (!arguments.length) {
+ stats = [];
+
+ for (k in _jobs)
+ stats.push(_jobs[k]);
+
+ for (k in _waitingJobs)
+ stats.push(_waitingJobs[k]);
+
+ for (k in _runningJobs)
+ stats.push(_runningJobs[k]);
+
+ stats = stats.concat(_doneJobs);
+ }
+
+ if (typeof v1 === 'string')
+ switch (v1) {
+ case 'waiting':
+ stats = __objectValues(_waitingJobs);
+ break;
+ case 'running':
+ stats = __objectValues(_runningJobs);
+ break;
+ case 'done':
+ stats = _doneJobs;
+ break;
+ default:
+ pattern = v1;
+ }
+
+ if (v1 instanceof RegExp)
+ pattern = v1;
+
+ if (!pattern && (typeof v2 === 'string' || v2 instanceof RegExp))
+ pattern = v2;
+
+ // Filter jobs if a pattern is given:
+ if (pattern) {
+ isPatternString = typeof pattern === 'string';
+
+ if (stats instanceof Array) {
+ a = stats;
+ } else if (typeof stats === 'object') {
+ a = [];
+
+ for (k in stats)
+ a = a.concat(stats[k]);
+ } else {
+ a = [];
+
+ for (k in _jobs)
+ a.push(_jobs[k]);
+
+ for (k in _waitingJobs)
+ a.push(_waitingJobs[k]);
+
+ for (k in _runningJobs)
+ a.push(_runningJobs[k]);
+
+ a = a.concat(_doneJobs);
+ }
+
+ stats = [];
+ for (i = 0, l = a.length; i < l; i++)
+ if (isPatternString ? a[i].id === pattern : a[i].id.match(pattern))
+ stats.push(a[i]);
+ }
+
+ return __clone(stats);
+ }
+
+
+ /**
+ * TOOLS FUNCTIONS:
+ * ****************
+ */
+
+ /**
+ * This function takes any number of objects as arguments, copies from each
+ * of these objects each pair key/value into a new object, and finally
+ * returns this object.
+ *
+ * The arguments are parsed from the last one to the first one, such that
+ * when two objects have keys in common, the "earliest" object wins.
+ *
+ * Example:
+ * ********
+ * > var o1 = {
+ * > a: 1,
+ * > b: 2,
+ * > c: '3'
+ * > },
+ * > o2 = {
+ * > c: '4',
+ * > d: [ 5 ]
+ * > };
+ * > __extend(o1, o2);
+ * > // Returns: {
+ * > // a: 1,
+ * > // b: 2,
+ * > // c: '3',
+ * > // d: [ 5 ]
+ * > // };
+ *
+ * @param {Object+} Any number of objects.
+ * @return {Object} The merged object.
+ */
+ function __extend() {
+ var i,
+ k,
+ res = {},
+ l = arguments.length;
+
+ for (i = l - 1; i >= 0; i--)
+ for (k in arguments[i])
+ res[k] = arguments[i][k];
+
+ return res;
+ }
+
+ /**
+ * This function simply clones an object. This object must contain only
+ * objects, arrays and immutable values. Since it is not public, it does not
+ * deal with cyclic references, DOM elements and instantiated objects - so
+ * use it carefully.
+ *
+ * @param {Object} The object to clone.
+ * @return {Object} The clone.
+ */
+ function __clone(item) {
+ var result, i, k, l;
+
+ if (!item)
+ return item;
+
+ if (Array.isArray(item)) {
+ result = [];
+ for (i = 0, l = item.length; i < l; i++)
+ result.push(__clone(item[i]));
+ } else if (typeof item === 'object') {
+ result = {};
+ for (i in item)
+ result[i] = __clone(item[i]);
+ } else
+ result = item;
+
+ return result;
+ }
+
+ /**
+ * Returns an array containing the values of an object.
+ *
+ * @param {Object} The object.
+ * @return {Array} The array of values.
+ */
+ function __objectValues(o) {
+ var k,
+ a = [];
+
+ for (k in o)
+ a.push(o[k]);
+
+ return a;
+ }
+
+ /**
+ * A short "Date.now()" polyfill.
+ *
+ * @return {Number} The current time (in ms).
+ */
+ function __dateNow() {
+ return Date.now ? Date.now() : new Date().getTime();
+ }
+
+ /**
+ * Polyfill for the Array.isArray function:
+ */
+ if (!Array.isArray)
+ Array.isArray = function(v) {
+ return Object.prototype.toString.call(v) === '[object Array]';
+ };
+
+
+ /**
+ * EXPORT PUBLIC API:
+ * ******************
+ */
+ var conrad = {
+ hasJob: _hasJob,
+ addJob: _addJob,
+ killJob: _killJob,
+ killAll: _killAll,
+ settings: _settings,
+ getStats: _getStats,
+ isRunning: _getIsRunning,
+ clearHistory: _clearHistory,
+
+ // Events management:
+ bind: _bind,
+ unbind: _unbind,
+
+ // Version:
+ version: '0.1.0'
+ };
+
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports)
+ exports = module.exports = conrad;
+ exports.conrad = conrad;
+ }
+ global.conrad = conrad;
+})(this);
diff --git a/blogContent/projects/steam/src/middlewares/sigma.middlewares.copy.js b/blogContent/projects/steam/src/middlewares/sigma.middlewares.copy.js
new file mode 100644
index 0000000..8f1b2a9
--- /dev/null
+++ b/blogContent/projects/steam/src/middlewares/sigma.middlewares.copy.js
@@ -0,0 +1,35 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.middlewares');
+
+ /**
+ * This middleware will just copy the graphic properties.
+ *
+ * @param {?string} readPrefix The read prefix.
+ * @param {?string} writePrefix The write prefix.
+ */
+ sigma.middlewares.copy = function(readPrefix, writePrefix) {
+ var i,
+ l,
+ a;
+
+ if (writePrefix + '' === readPrefix + '')
+ return;
+
+ a = this.graph.nodes();
+ for (i = 0, l = a.length; i < l; i++) {
+ a[i][writePrefix + 'x'] = a[i][readPrefix + 'x'];
+ a[i][writePrefix + 'y'] = a[i][readPrefix + 'y'];
+ a[i][writePrefix + 'size'] = a[i][readPrefix + 'size'];
+ }
+
+ a = this.graph.edges();
+ for (i = 0, l = a.length; i < l; i++)
+ a[i][writePrefix + 'size'] = a[i][readPrefix + 'size'];
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/middlewares/sigma.middlewares.rescale.js b/blogContent/projects/steam/src/middlewares/sigma.middlewares.rescale.js
new file mode 100644
index 0000000..85460ec
--- /dev/null
+++ b/blogContent/projects/steam/src/middlewares/sigma.middlewares.rescale.js
@@ -0,0 +1,189 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.middlewares');
+ sigma.utils.pkg('sigma.utils');
+
+ /**
+ * This middleware will rescale the graph such that it takes an optimal space
+ * on the renderer.
+ *
+ * As each middleware, this function is executed in the scope of the sigma
+ * instance.
+ *
+ * @param {?string} readPrefix The read prefix.
+ * @param {?string} writePrefix The write prefix.
+ * @param {object} options The parameters.
+ */
+ sigma.middlewares.rescale = function(readPrefix, writePrefix, options) {
+ var i,
+ l,
+ a,
+ b,
+ c,
+ d,
+ scale,
+ margin,
+ n = this.graph.nodes(),
+ e = this.graph.edges(),
+ settings = this.settings.embedObjects(options || {}),
+ bounds = settings('bounds') || sigma.utils.getBoundaries(
+ this.graph,
+ readPrefix,
+ true
+ ),
+ minX = bounds.minX,
+ minY = bounds.minY,
+ maxX = bounds.maxX,
+ maxY = bounds.maxY,
+ sizeMax = bounds.sizeMax,
+ weightMax = bounds.weightMax,
+ w = settings('width') || 1,
+ h = settings('height') || 1,
+ rescaleSettings = settings('autoRescale'),
+ validSettings = {
+ nodePosition: 1,
+ nodeSize: 1,
+ edgeSize: 1
+ };
+
+ /**
+ * What elements should we rescale?
+ */
+ if (!(rescaleSettings instanceof Array))
+ rescaleSettings = ['nodePosition', 'nodeSize', 'edgeSize'];
+
+ for (i = 0, l = rescaleSettings.length; i < l; i++)
+ if (!validSettings[rescaleSettings[i]])
+ throw new Error(
+ 'The rescale setting "' + rescaleSettings[i] + '" is not recognized.'
+ );
+
+ var np = ~rescaleSettings.indexOf('nodePosition'),
+ ns = ~rescaleSettings.indexOf('nodeSize'),
+ es = ~rescaleSettings.indexOf('edgeSize');
+
+ /**
+ * First, we compute the scaling ratio, without considering the sizes
+ * of the nodes : Each node will have its center in the canvas, but might
+ * be partially out of it.
+ */
+ scale = settings('scalingMode') === 'outside' ?
+ Math.max(
+ w / Math.max(maxX - minX, 1),
+ h / Math.max(maxY - minY, 1)
+ ) :
+ Math.min(
+ w / Math.max(maxX - minX, 1),
+ h / Math.max(maxY - minY, 1)
+ );
+
+ /**
+ * Then, we correct that scaling ratio considering a margin, which is
+ * basically the size of the biggest node.
+ * This has to be done as a correction since to compare the size of the
+ * biggest node to the X and Y values, we have to first get an
+ * approximation of the scaling ratio.
+ **/
+ margin =
+ (
+ settings('rescaleIgnoreSize') ?
+ 0 :
+ (settings('maxNodeSize') || sizeMax) / scale
+ ) +
+ (settings('sideMargin') || 0);
+ maxX += margin;
+ minX -= margin;
+ maxY += margin;
+ minY -= margin;
+
+ // Fix the scaling with the new extrema:
+ scale = settings('scalingMode') === 'outside' ?
+ Math.max(
+ w / Math.max(maxX - minX, 1),
+ h / Math.max(maxY - minY, 1)
+ ) :
+ Math.min(
+ w / Math.max(maxX - minX, 1),
+ h / Math.max(maxY - minY, 1)
+ );
+
+ // Size homothetic parameters:
+ if (!settings('maxNodeSize') && !settings('minNodeSize')) {
+ a = 1;
+ b = 0;
+ } else if (settings('maxNodeSize') === settings('minNodeSize')) {
+ a = 0;
+ b = +settings('maxNodeSize');
+ } else {
+ a = (settings('maxNodeSize') - settings('minNodeSize')) / sizeMax;
+ b = +settings('minNodeSize');
+ }
+
+ if (!settings('maxEdgeSize') && !settings('minEdgeSize')) {
+ c = 1;
+ d = 0;
+ } else if (settings('maxEdgeSize') === settings('minEdgeSize')) {
+ c = 0;
+ d = +settings('minEdgeSize');
+ } else {
+ c = (settings('maxEdgeSize') - settings('minEdgeSize')) / weightMax;
+ d = +settings('minEdgeSize');
+ }
+
+ // Rescale the nodes and edges:
+ for (i = 0, l = e.length; i < l; i++)
+ e[i][writePrefix + 'size'] =
+ e[i][readPrefix + 'size'] * (es ? c : 1) + (es ? d : 0);
+
+ for (i = 0, l = n.length; i < l; i++) {
+ n[i][writePrefix + 'size'] =
+ n[i][readPrefix + 'size'] * (ns ? a : 1) + (ns ? b : 0);
+ n[i][writePrefix + 'x'] =
+ (n[i][readPrefix + 'x'] - (maxX + minX) / 2) * (np ? scale : 1);
+ n[i][writePrefix + 'y'] =
+ (n[i][readPrefix + 'y'] - (maxY + minY) / 2) * (np ? scale : 1);
+ }
+ };
+
+ sigma.utils.getBoundaries = function(graph, prefix, doEdges) {
+ var i,
+ l,
+ e = graph.edges(),
+ n = graph.nodes(),
+ weightMax = -Infinity,
+ sizeMax = -Infinity,
+ minX = Infinity,
+ minY = Infinity,
+ maxX = -Infinity,
+ maxY = -Infinity;
+
+ if (doEdges)
+ for (i = 0, l = e.length; i < l; i++)
+ weightMax = Math.max(e[i][prefix + 'size'], weightMax);
+
+ for (i = 0, l = n.length; i < l; i++) {
+ sizeMax = Math.max(n[i][prefix + 'size'], sizeMax);
+ maxX = Math.max(n[i][prefix + 'x'], maxX);
+ minX = Math.min(n[i][prefix + 'x'], minX);
+ maxY = Math.max(n[i][prefix + 'y'], maxY);
+ minY = Math.min(n[i][prefix + 'y'], minY);
+ }
+
+ weightMax = weightMax || 1;
+ sizeMax = sizeMax || 1;
+
+ return {
+ weightMax: weightMax,
+ sizeMax: sizeMax,
+ minX: minX,
+ minY: minY,
+ maxX: maxX,
+ maxY: maxY
+ };
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/misc/sigma.misc.animation.js b/blogContent/projects/steam/src/misc/sigma.misc.animation.js
new file mode 100644
index 0000000..299f00f
--- /dev/null
+++ b/blogContent/projects/steam/src/misc/sigma.misc.animation.js
@@ -0,0 +1,239 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.misc.animation.running');
+
+ /**
+ * Generates a unique ID for the animation.
+ *
+ * @return {string} Returns the new ID.
+ */
+ var _getID = (function() {
+ var id = 0;
+ return function() {
+ return '' + (++id);
+ };
+ })();
+
+ /**
+ * This function animates a camera. It has to be called with the camera to
+ * animate, the values of the coordinates to reach and eventually some
+ * options. It returns a number id, that you can use to kill the animation,
+ * with the method sigma.misc.animation.kill(id).
+ *
+ * The available options are:
+ *
+ * {?number} duration The duration of the animation.
+ * {?function} onNewFrame A callback to execute when the animation
+ * enter a new frame.
+ * {?function} onComplete A callback to execute when the animation
+ * is completed or killed.
+ * {?(string|function)} easing The name of a function from the package
+ * sigma.utils.easings, or a custom easing
+ * function.
+ *
+ * @param {camera} camera The camera to animate.
+ * @param {object} target The coordinates to reach.
+ * @param {?object} options Eventually an object to specify some options to
+ * the function. The available options are
+ * presented in the description of the function.
+ * @return {number} The animation id, to make it easy to kill
+ * through the method "sigma.misc.animation.kill".
+ */
+ sigma.misc.animation.camera = function(camera, val, options) {
+ if (
+ !(camera instanceof sigma.classes.camera) ||
+ typeof val !== 'object' ||
+ !val
+ )
+ throw 'animation.camera: Wrong arguments.';
+
+ if (
+ typeof val.x !== 'number' &&
+ typeof val.y !== 'number' &&
+ typeof val.ratio !== 'number' &&
+ typeof val.angle !== 'number'
+ )
+ throw 'There must be at least one valid coordinate in the given val.';
+
+ var fn,
+ id,
+ anim,
+ easing,
+ duration,
+ initialVal,
+ o = options || {},
+ start = sigma.utils.dateNow();
+
+ // Store initial values:
+ initialVal = {
+ x: camera.x,
+ y: camera.y,
+ ratio: camera.ratio,
+ angle: camera.angle
+ };
+
+ duration = o.duration;
+ easing = typeof o.easing !== 'function' ?
+ sigma.utils.easings[o.easing || 'quadraticInOut'] :
+ o.easing;
+
+ fn = function() {
+ var coef,
+ t = o.duration ? (sigma.utils.dateNow() - start) / o.duration : 1;
+
+ // If the animation is over:
+ if (t >= 1) {
+ camera.isAnimated = false;
+ camera.goTo({
+ x: val.x !== undefined ? val.x : initialVal.x,
+ y: val.y !== undefined ? val.y : initialVal.y,
+ ratio: val.ratio !== undefined ? val.ratio : initialVal.ratio,
+ angle: val.angle !== undefined ? val.angle : initialVal.angle
+ });
+
+ cancelAnimationFrame(id);
+ delete sigma.misc.animation.running[id];
+
+ // Check callbacks:
+ if (typeof o.onComplete === 'function')
+ o.onComplete();
+
+ // Else, let's keep going:
+ } else {
+ coef = easing(t);
+ camera.isAnimated = true;
+ camera.goTo({
+ x: val.x !== undefined ?
+ initialVal.x + (val.x - initialVal.x) * coef :
+ initialVal.x,
+ y: val.y !== undefined ?
+ initialVal.y + (val.y - initialVal.y) * coef :
+ initialVal.y,
+ ratio: val.ratio !== undefined ?
+ initialVal.ratio + (val.ratio - initialVal.ratio) * coef :
+ initialVal.ratio,
+ angle: val.angle !== undefined ?
+ initialVal.angle + (val.angle - initialVal.angle) * coef :
+ initialVal.angle
+ });
+
+ // Check callbacks:
+ if (typeof o.onNewFrame === 'function')
+ o.onNewFrame();
+
+ anim.frameId = requestAnimationFrame(fn);
+ }
+ };
+
+ id = _getID();
+ anim = {
+ frameId: requestAnimationFrame(fn),
+ target: camera,
+ type: 'camera',
+ options: o,
+ fn: fn
+ };
+ sigma.misc.animation.running[id] = anim;
+
+ return id;
+ };
+
+ /**
+ * Kills a running animation. It triggers the eventual onComplete callback.
+ *
+ * @param {number} id The id of the animation to kill.
+ * @return {object} Returns the sigma.misc.animation package.
+ */
+ sigma.misc.animation.kill = function(id) {
+ if (arguments.length !== 1 || typeof id !== 'number')
+ throw 'animation.kill: Wrong arguments.';
+
+ var o = sigma.misc.animation.running[id];
+
+ if (o) {
+ cancelAnimationFrame(id);
+ delete sigma.misc.animation.running[o.frameId];
+
+ if (o.type === 'camera')
+ o.target.isAnimated = false;
+
+ // Check callbacks:
+ if (typeof (o.options || {}).onComplete === 'function')
+ o.options.onComplete();
+ }
+
+ return this;
+ };
+
+ /**
+ * Kills every running animations, or only the one with the specified type,
+ * if a string parameter is given.
+ *
+ * @param {?(string|object)} filter A string to filter the animations to kill
+ * on their type (example: "camera"), or an
+ * object to filter on their target.
+ * @return {number} Returns the number of animations killed
+ * that way.
+ */
+ sigma.misc.animation.killAll = function(filter) {
+ var o,
+ id,
+ count = 0,
+ type = typeof filter === 'string' ? filter : null,
+ target = typeof filter === 'object' ? filter : null,
+ running = sigma.misc.animation.running;
+
+ for (id in running)
+ if (
+ (!type || running[id].type === type) &&
+ (!target || running[id].target === target)
+ ) {
+ o = sigma.misc.animation.running[id];
+ cancelAnimationFrame(o.frameId);
+ delete sigma.misc.animation.running[id];
+
+ if (o.type === 'camera')
+ o.target.isAnimated = false;
+
+ // Increment counter:
+ count++;
+
+ // Check callbacks:
+ if (typeof (o.options || {}).onComplete === 'function')
+ o.options.onComplete();
+ }
+
+ return count;
+ };
+
+ /**
+ * Returns "true" if any animation that is currently still running matches
+ * the filter given to the function.
+ *
+ * @param {string|object} filter A string to filter the animations to kill
+ * on their type (example: "camera"), or an
+ * object to filter on their target.
+ * @return {boolean} Returns true if any running animation
+ * matches.
+ */
+ sigma.misc.animation.has = function(filter) {
+ var id,
+ type = typeof filter === 'string' ? filter : null,
+ target = typeof filter === 'object' ? filter : null,
+ running = sigma.misc.animation.running;
+
+ for (id in running)
+ if (
+ (!type || running[id].type === type) &&
+ (!target || running[id].target === target)
+ )
+ return true;
+
+ return false;
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/misc/sigma.misc.bindDOMEvents.js b/blogContent/projects/steam/src/misc/sigma.misc.bindDOMEvents.js
new file mode 100644
index 0000000..1e758e8
--- /dev/null
+++ b/blogContent/projects/steam/src/misc/sigma.misc.bindDOMEvents.js
@@ -0,0 +1,156 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.misc');
+
+ /**
+ * This helper will bind any DOM renderer (for instance svg)
+ * to its captors, to properly dispatch the good events to the sigma instance
+ * to manage clicking, hovering etc...
+ *
+ * It has to be called in the scope of the related renderer.
+ */
+ sigma.misc.bindDOMEvents = function(container) {
+ var self = this,
+ graph = this.graph;
+
+ // DOMElement abstraction
+ function Element(domElement) {
+
+ // Helpers
+ this.attr = function(attrName) {
+ return domElement.getAttributeNS(null, attrName);
+ };
+
+ // Properties
+ this.tag = domElement.tagName;
+ this.class = this.attr('class');
+ this.id = this.attr('id');
+
+ // Methods
+ this.isNode = function() {
+ return !!~this.class.indexOf(self.settings('classPrefix') + '-node');
+ };
+
+ this.isEdge = function() {
+ return !!~this.class.indexOf(self.settings('classPrefix') + '-edge');
+ };
+
+ this.isHover = function() {
+ return !!~this.class.indexOf(self.settings('classPrefix') + '-hover');
+ };
+ }
+
+ // Click
+ function click(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ // Generic event
+ self.dispatchEvent('click', e);
+
+ // Are we on a node?
+ var element = new Element(e.target);
+
+ if (element.isNode())
+ self.dispatchEvent('clickNode', {
+ node: graph.nodes(element.attr('data-node-id'))
+ });
+ else
+ self.dispatchEvent('clickStage');
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ // Double click
+ function doubleClick(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ // Generic event
+ self.dispatchEvent('doubleClick', e);
+
+ // Are we on a node?
+ var element = new Element(e.target);
+
+ if (element.isNode())
+ self.dispatchEvent('doubleClickNode', {
+ node: graph.nodes(element.attr('data-node-id'))
+ });
+ else
+ self.dispatchEvent('doubleClickStage');
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ // On over
+ function onOver(e) {
+ var target = e.toElement || e.target;
+
+ if (!self.settings('eventsEnabled') || !target)
+ return;
+
+ var el = new Element(target);
+
+ if (el.isNode()) {
+ self.dispatchEvent('overNode', {
+ node: graph.nodes(el.attr('data-node-id'))
+ });
+ }
+ else if (el.isEdge()) {
+ var edge = graph.edges(el.attr('data-edge-id'));
+ self.dispatchEvent('overEdge', {
+ edge: edge,
+ source: graph.nodes(edge.source),
+ target: graph.nodes(edge.target)
+ });
+ }
+ }
+
+ // On out
+ function onOut(e) {
+ var target = e.fromElement || e.originalTarget;
+
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ var el = new Element(target);
+
+ if (el.isNode()) {
+ self.dispatchEvent('outNode', {
+ node: graph.nodes(el.attr('data-node-id'))
+ });
+ }
+ else if (el.isEdge()) {
+ var edge = graph.edges(el.attr('data-edge-id'));
+ self.dispatchEvent('outEdge', {
+ edge: edge,
+ source: graph.nodes(edge.source),
+ target: graph.nodes(edge.target)
+ });
+ }
+ }
+
+ // Registering Events:
+
+ // Click
+ container.addEventListener('click', click, false);
+ sigma.utils.doubleClick(container, 'click', doubleClick);
+
+ // Touch counterparts
+ container.addEventListener('touchstart', click, false);
+ sigma.utils.doubleClick(container, 'touchstart', doubleClick);
+
+ // Mouseover
+ container.addEventListener('mouseover', onOver, true);
+
+ // Mouseout
+ container.addEventListener('mouseout', onOut, true);
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/misc/sigma.misc.bindEvents.js b/blogContent/projects/steam/src/misc/sigma.misc.bindEvents.js
new file mode 100644
index 0000000..e87ad02
--- /dev/null
+++ b/blogContent/projects/steam/src/misc/sigma.misc.bindEvents.js
@@ -0,0 +1,509 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.misc');
+
+ /**
+ * This helper will bind any no-DOM renderer (for instance canvas or WebGL)
+ * to its captors, to properly dispatch the good events to the sigma instance
+ * to manage clicking, hovering etc...
+ *
+ * It has to be called in the scope of the related renderer.
+ */
+ sigma.misc.bindEvents = function(prefix) {
+ var i,
+ l,
+ mX,
+ mY,
+ captor,
+ self = this;
+
+ function getNodes(e) {
+ if (e) {
+ mX = 'x' in e.data ? e.data.x : mX;
+ mY = 'y' in e.data ? e.data.y : mY;
+ }
+
+ var i,
+ j,
+ l,
+ n,
+ x,
+ y,
+ s,
+ inserted,
+ selected = [],
+ modifiedX = mX + self.width / 2,
+ modifiedY = mY + self.height / 2,
+ point = self.camera.cameraPosition(
+ mX,
+ mY
+ ),
+ nodes = self.camera.quadtree.point(
+ point.x,
+ point.y
+ );
+
+ if (nodes.length)
+ for (i = 0, l = nodes.length; i < l; i++) {
+ n = nodes[i];
+ x = n[prefix + 'x'];
+ y = n[prefix + 'y'];
+ s = n[prefix + 'size'];
+
+ if (
+ !n.hidden &&
+ modifiedX > x - s &&
+ modifiedX < x + s &&
+ modifiedY > y - s &&
+ modifiedY < y + s &&
+ Math.sqrt(
+ Math.pow(modifiedX - x, 2) +
+ Math.pow(modifiedY - y, 2)
+ ) < s
+ ) {
+ // Insert the node:
+ inserted = false;
+
+ for (j = 0; j < selected.length; j++)
+ if (n.size > selected[j].size) {
+ selected.splice(j, 0, n);
+ inserted = true;
+ break;
+ }
+
+ if (!inserted)
+ selected.push(n);
+ }
+ }
+
+ return selected;
+ }
+
+
+ function getEdges(e) {
+ if (!self.settings('enableEdgeHovering')) {
+ // No event if the setting is off:
+ return [];
+ }
+
+ var isCanvas = (
+ sigma.renderers.canvas && self instanceof sigma.renderers.canvas);
+
+ if (!isCanvas) {
+ // A quick hardcoded rule to prevent people from using this feature
+ // with the WebGL renderer (which is not good enough at the moment):
+ throw new Error(
+ 'The edge events feature is not compatible with the WebGL renderer'
+ );
+ }
+
+ if (e) {
+ mX = 'x' in e.data ? e.data.x : mX;
+ mY = 'y' in e.data ? e.data.y : mY;
+ }
+
+ var i,
+ j,
+ l,
+ a,
+ edge,
+ s,
+ maxEpsilon = self.settings('edgeHoverPrecision'),
+ source,
+ target,
+ cp,
+ nodeIndex = {},
+ inserted,
+ selected = [],
+ modifiedX = mX + self.width / 2,
+ modifiedY = mY + self.height / 2,
+ point = self.camera.cameraPosition(
+ mX,
+ mY
+ ),
+ edges = [];
+
+ if (isCanvas) {
+ var nodesOnScreen = self.camera.quadtree.area(
+ self.camera.getRectangle(self.width, self.height)
+ );
+ for (a = nodesOnScreen, i = 0, l = a.length; i < l; i++)
+ nodeIndex[a[i].id] = a[i];
+ }
+
+ if (self.camera.edgequadtree !== undefined) {
+ edges = self.camera.edgequadtree.point(
+ point.x,
+ point.y
+ );
+ }
+
+ function insertEdge(selected, edge) {
+ inserted = false;
+
+ for (j = 0; j < selected.length; j++)
+ if (edge.size > selected[j].size) {
+ selected.splice(j, 0, edge);
+ inserted = true;
+ break;
+ }
+
+ if (!inserted)
+ selected.push(edge);
+ }
+
+ if (edges.length)
+ for (i = 0, l = edges.length; i < l; i++) {
+ edge = edges[i];
+ source = self.graph.nodes(edge.source);
+ target = self.graph.nodes(edge.target);
+ // (HACK) we can't get edge[prefix + 'size'] on WebGL renderer:
+ s = edge[prefix + 'size'] ||
+ edge['read_' + prefix + 'size'];
+
+ // First, let's identify which edges are drawn. To do this, we keep
+ // every edges that have at least one extremity displayed according to
+ // the quadtree and the "hidden" attribute. We also do not keep hidden
+ // edges.
+ // Then, let's check if the mouse is on the edge (we suppose that it
+ // is a line segment).
+
+ if (
+ !edge.hidden &&
+ !source.hidden && !target.hidden &&
+ (!isCanvas ||
+ (nodeIndex[edge.source] || nodeIndex[edge.target])) &&
+ sigma.utils.getDistance(
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ modifiedX,
+ modifiedY) > source[prefix + 'size'] &&
+ sigma.utils.getDistance(
+ target[prefix + 'x'],
+ target[prefix + 'y'],
+ modifiedX,
+ modifiedY) > target[prefix + 'size']
+ ) {
+ if (edge.type == 'curve' || edge.type == 'curvedArrow') {
+ if (source.id === target.id) {
+ cp = sigma.utils.getSelfLoopControlPoints(
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ source[prefix + 'size']
+ );
+ if (
+ sigma.utils.isPointOnBezierCurve(
+ modifiedX,
+ modifiedY,
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ target[prefix + 'x'],
+ target[prefix + 'y'],
+ cp.x1,
+ cp.y1,
+ cp.x2,
+ cp.y2,
+ Math.max(s, maxEpsilon)
+ )) {
+ insertEdge(selected, edge);
+ }
+ }
+ else {
+ cp = sigma.utils.getQuadraticControlPoint(
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ target[prefix + 'x'],
+ target[prefix + 'y']);
+ if (
+ sigma.utils.isPointOnQuadraticCurve(
+ modifiedX,
+ modifiedY,
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ target[prefix + 'x'],
+ target[prefix + 'y'],
+ cp.x,
+ cp.y,
+ Math.max(s, maxEpsilon)
+ )) {
+ insertEdge(selected, edge);
+ }
+ }
+ } else if (
+ sigma.utils.isPointOnSegment(
+ modifiedX,
+ modifiedY,
+ source[prefix + 'x'],
+ source[prefix + 'y'],
+ target[prefix + 'x'],
+ target[prefix + 'y'],
+ Math.max(s, maxEpsilon)
+ )) {
+ insertEdge(selected, edge);
+ }
+ }
+ }
+
+ return selected;
+ }
+
+
+ function bindCaptor(captor) {
+ var nodes,
+ edges,
+ overNodes = {},
+ overEdges = {};
+
+ function onClick(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ self.dispatchEvent('click', e.data);
+
+ nodes = getNodes(e);
+ edges = getEdges(e);
+
+ if (nodes.length) {
+ self.dispatchEvent('clickNode', {
+ node: nodes[0],
+ captor: e.data
+ });
+ self.dispatchEvent('clickNodes', {
+ node: nodes,
+ captor: e.data
+ });
+ } else if (edges.length) {
+ self.dispatchEvent('clickEdge', {
+ edge: edges[0],
+ captor: e.data
+ });
+ self.dispatchEvent('clickEdges', {
+ edge: edges,
+ captor: e.data
+ });
+ } else
+ self.dispatchEvent('clickStage', {captor: e.data});
+ }
+
+ function onDoubleClick(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ self.dispatchEvent('doubleClick', e.data);
+
+ nodes = getNodes(e);
+ edges = getEdges(e);
+
+ if (nodes.length) {
+ self.dispatchEvent('doubleClickNode', {
+ node: nodes[0],
+ captor: e.data
+ });
+ self.dispatchEvent('doubleClickNodes', {
+ node: nodes,
+ captor: e.data
+ });
+ } else if (edges.length) {
+ self.dispatchEvent('doubleClickEdge', {
+ edge: edges[0],
+ captor: e.data
+ });
+ self.dispatchEvent('doubleClickEdges', {
+ edge: edges,
+ captor: e.data
+ });
+ } else
+ self.dispatchEvent('doubleClickStage', {captor: e.data});
+ }
+
+ function onRightClick(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ self.dispatchEvent('rightClick', e.data);
+
+ nodes = getNodes(e);
+ edges = getEdges(e);
+
+ if (nodes.length) {
+ self.dispatchEvent('rightClickNode', {
+ node: nodes[0],
+ captor: e.data
+ });
+ self.dispatchEvent('rightClickNodes', {
+ node: nodes,
+ captor: e.data
+ });
+ } else if (edges.length) {
+ self.dispatchEvent('rightClickEdge', {
+ edge: edges[0],
+ captor: e.data
+ });
+ self.dispatchEvent('rightClickEdges', {
+ edge: edges,
+ captor: e.data
+ });
+ } else
+ self.dispatchEvent('rightClickStage', {captor: e.data});
+ }
+
+ function onOut(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ var k,
+ i,
+ l,
+ le,
+ outNodes = [],
+ outEdges = [];
+
+ for (k in overNodes)
+ outNodes.push(overNodes[k]);
+
+ overNodes = {};
+ // Dispatch both single and multi events:
+ for (i = 0, l = outNodes.length; i < l; i++)
+ self.dispatchEvent('outNode', {
+ node: outNodes[i],
+ captor: e.data
+ });
+ if (outNodes.length)
+ self.dispatchEvent('outNodes', {
+ nodes: outNodes,
+ captor: e.data
+ });
+
+ overEdges = {};
+ // Dispatch both single and multi events:
+ for (i = 0, le = outEdges.length; i < le; i++)
+ self.dispatchEvent('outEdge', {
+ edge: outEdges[i],
+ captor: e.data
+ });
+ if (outEdges.length)
+ self.dispatchEvent('outEdges', {
+ edges: outEdges,
+ captor: e.data
+ });
+ }
+
+ function onMove(e) {
+ if (!self.settings('eventsEnabled'))
+ return;
+
+ nodes = getNodes(e);
+ edges = getEdges(e);
+
+ var i,
+ k,
+ node,
+ edge,
+ newOutNodes = [],
+ newOverNodes = [],
+ currentOverNodes = {},
+ l = nodes.length,
+ newOutEdges = [],
+ newOverEdges = [],
+ currentOverEdges = {},
+ le = edges.length;
+
+ // Check newly overred nodes:
+ for (i = 0; i < l; i++) {
+ node = nodes[i];
+ currentOverNodes[node.id] = node;
+ if (!overNodes[node.id]) {
+ newOverNodes.push(node);
+ overNodes[node.id] = node;
+ }
+ }
+
+ // Check no more overred nodes:
+ for (k in overNodes)
+ if (!currentOverNodes[k]) {
+ newOutNodes.push(overNodes[k]);
+ delete overNodes[k];
+ }
+
+ // Dispatch both single and multi events:
+ for (i = 0, l = newOverNodes.length; i < l; i++)
+ self.dispatchEvent('overNode', {
+ node: newOverNodes[i],
+ captor: e.data
+ });
+ for (i = 0, l = newOutNodes.length; i < l; i++)
+ self.dispatchEvent('outNode', {
+ node: newOutNodes[i],
+ captor: e.data
+ });
+ if (newOverNodes.length)
+ self.dispatchEvent('overNodes', {
+ nodes: newOverNodes,
+ captor: e.data
+ });
+ if (newOutNodes.length)
+ self.dispatchEvent('outNodes', {
+ nodes: newOutNodes,
+ captor: e.data
+ });
+
+ // Check newly overred edges:
+ for (i = 0; i < le; i++) {
+ edge = edges[i];
+ currentOverEdges[edge.id] = edge;
+ if (!overEdges[edge.id]) {
+ newOverEdges.push(edge);
+ overEdges[edge.id] = edge;
+ }
+ }
+
+ // Check no more overred edges:
+ for (k in overEdges)
+ if (!currentOverEdges[k]) {
+ newOutEdges.push(overEdges[k]);
+ delete overEdges[k];
+ }
+
+ // Dispatch both single and multi events:
+ for (i = 0, le = newOverEdges.length; i < le; i++)
+ self.dispatchEvent('overEdge', {
+ edge: newOverEdges[i],
+ captor: e.data
+ });
+ for (i = 0, le = newOutEdges.length; i < le; i++)
+ self.dispatchEvent('outEdge', {
+ edge: newOutEdges[i],
+ captor: e.data
+ });
+ if (newOverEdges.length)
+ self.dispatchEvent('overEdges', {
+ edges: newOverEdges,
+ captor: e.data
+ });
+ if (newOutEdges.length)
+ self.dispatchEvent('outEdges', {
+ edges: newOutEdges,
+ captor: e.data
+ });
+ }
+
+ // Bind events:
+ captor.bind('click', onClick);
+ captor.bind('mousedown', onMove);
+ captor.bind('mouseup', onMove);
+ captor.bind('mousemove', onMove);
+ captor.bind('mouseout', onOut);
+ captor.bind('doubleclick', onDoubleClick);
+ captor.bind('rightclick', onRightClick);
+ self.bind('render', onMove);
+ }
+
+ for (i = 0, l = this.captors.length; i < l; i++)
+ bindCaptor(this.captors[i]);
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/misc/sigma.misc.drawHovers.js b/blogContent/projects/steam/src/misc/sigma.misc.drawHovers.js
new file mode 100644
index 0000000..82fafec
--- /dev/null
+++ b/blogContent/projects/steam/src/misc/sigma.misc.drawHovers.js
@@ -0,0 +1,222 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ // Initialize packages:
+ sigma.utils.pkg('sigma.misc');
+
+ /**
+ * This method listens to "overNode", "outNode", "overEdge" and "outEdge"
+ * events from a renderer and renders the nodes differently on the top layer.
+ * The goal is to make any node label readable with the mouse, and to
+ * highlight hovered nodes and edges.
+ *
+ * It has to be called in the scope of the related renderer.
+ */
+ sigma.misc.drawHovers = function(prefix) {
+ var self = this,
+ hoveredNodes = {},
+ hoveredEdges = {};
+
+ this.bind('overNode', function(event) {
+ var node = event.data.node;
+ if (!node.hidden) {
+ hoveredNodes[node.id] = node;
+ draw();
+ }
+ });
+
+ this.bind('outNode', function(event) {
+ delete hoveredNodes[event.data.node.id];
+ draw();
+ });
+
+ this.bind('overEdge', function(event) {
+ var edge = event.data.edge;
+ if (!edge.hidden) {
+ hoveredEdges[edge.id] = edge;
+ draw();
+ }
+ });
+
+ this.bind('outEdge', function(event) {
+ delete hoveredEdges[event.data.edge.id];
+ draw();
+ });
+
+ this.bind('render', function(event) {
+ draw();
+ });
+
+ function draw() {
+
+ var k,
+ source,
+ target,
+ hoveredNode,
+ hoveredEdge,
+ c = self.contexts.hover.canvas,
+ defaultNodeType = self.settings('defaultNodeType'),
+ defaultEdgeType = self.settings('defaultEdgeType'),
+ nodeRenderers = sigma.canvas.hovers,
+ edgeRenderers = sigma.canvas.edgehovers,
+ extremitiesRenderers = sigma.canvas.extremities,
+ embedSettings = self.settings.embedObjects({
+ prefix: prefix
+ });
+
+ // Clear self.contexts.hover:
+ self.contexts.hover.clearRect(0, 0, c.width, c.height);
+
+ // Node render: single hover
+ if (
+ embedSettings('enableHovering') &&
+ embedSettings('singleHover') &&
+ Object.keys(hoveredNodes).length
+ ) {
+ hoveredNode = hoveredNodes[Object.keys(hoveredNodes)[0]];
+ (
+ nodeRenderers[hoveredNode.type] ||
+ nodeRenderers[defaultNodeType] ||
+ nodeRenderers.def
+ )(
+ hoveredNode,
+ self.contexts.hover,
+ embedSettings
+ );
+ }
+
+ // Node render: multiple hover
+ if (
+ embedSettings('enableHovering') &&
+ !embedSettings('singleHover')
+ )
+ for (k in hoveredNodes)
+ (
+ nodeRenderers[hoveredNodes[k].type] ||
+ nodeRenderers[defaultNodeType] ||
+ nodeRenderers.def
+ )(
+ hoveredNodes[k],
+ self.contexts.hover,
+ embedSettings
+ );
+
+ // Edge render: single hover
+ if (
+ embedSettings('enableEdgeHovering') &&
+ embedSettings('singleHover') &&
+ Object.keys(hoveredEdges).length
+ ) {
+ hoveredEdge = hoveredEdges[Object.keys(hoveredEdges)[0]];
+ source = self.graph.nodes(hoveredEdge.source);
+ target = self.graph.nodes(hoveredEdge.target);
+
+ if (! hoveredEdge.hidden) {
+ (
+ edgeRenderers[hoveredEdge.type] ||
+ edgeRenderers[defaultEdgeType] ||
+ edgeRenderers.def
+ ) (
+ hoveredEdge,
+ source,
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+
+ if (embedSettings('edgeHoverExtremities')) {
+ (
+ extremitiesRenderers[hoveredEdge.type] ||
+ extremitiesRenderers.def
+ )(
+ hoveredEdge,
+ source,
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+
+ } else {
+ // Avoid edges rendered over nodes:
+ (
+ sigma.canvas.nodes[source.type] ||
+ sigma.canvas.nodes.def
+ ) (
+ source,
+ self.contexts.hover,
+ embedSettings
+ );
+ (
+ sigma.canvas.nodes[target.type] ||
+ sigma.canvas.nodes.def
+ ) (
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+ }
+ }
+ }
+
+ // Edge render: multiple hover
+ if (
+ embedSettings('enableEdgeHovering') &&
+ !embedSettings('singleHover')
+ ) {
+ for (k in hoveredEdges) {
+ hoveredEdge = hoveredEdges[k];
+ source = self.graph.nodes(hoveredEdge.source);
+ target = self.graph.nodes(hoveredEdge.target);
+
+ if (!hoveredEdge.hidden) {
+ (
+ edgeRenderers[hoveredEdge.type] ||
+ edgeRenderers[defaultEdgeType] ||
+ edgeRenderers.def
+ ) (
+ hoveredEdge,
+ source,
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+
+ if (embedSettings('edgeHoverExtremities')) {
+ (
+ extremitiesRenderers[hoveredEdge.type] ||
+ extremitiesRenderers.def
+ )(
+ hoveredEdge,
+ source,
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+ } else {
+ // Avoid edges rendered over nodes:
+ (
+ sigma.canvas.nodes[source.type] ||
+ sigma.canvas.nodes.def
+ ) (
+ source,
+ self.contexts.hover,
+ embedSettings
+ );
+ (
+ sigma.canvas.nodes[target.type] ||
+ sigma.canvas.nodes.def
+ ) (
+ target,
+ self.contexts.hover,
+ embedSettings
+ );
+ }
+ }
+ }
+ }
+ }
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/plugins/sigma.exporters.svg/README.md b/blogContent/projects/steam/src/plugins/sigma.exporters.svg/README.md
new file mode 100644
index 0000000..bc188e6
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.exporters.svg/README.md
@@ -0,0 +1,41 @@
+sigma.exporters.svg
+========================
+
+Plugin by [Guillaume Plique](https://github.com/Yomguithereal).
+
+---
+
+This plugin aims at providing an easy way to export a graph as a SVG file.
+
+*Basic usage*
+
+```js
+// Retrieving the svg file as a string
+var svgString = sigInst.toSVG();
+
+// Dowload the svg file
+sigInst.toSVG({download: true, filename: 'my-fancy-graph.svg'});
+```
+
+*Complex usage*
+
+```js
+sigInst.toSVG({
+ labels: true,
+ classes: false,
+ data: true,
+ download: true,
+ filename: 'hello.svg'
+});
+```
+
+*Parameters*
+
+* **size** *?integer* [`1000`]: size of the svg canvas in pixels.
+* **height** *?integer* [`1000`]: height of the svg canvas in pixels (useful only if you want a height different from the width).
+* **width** *?integer* [`1000`]: width of the svg canvas in pixels (useful only if you want a width different from the height).
+* **classes** *?boolean* [`true`]: should the exporter try to optimize the svg document by creating classes?
+* **labels** *?boolean* [`false`]: should the labels be included in the svg file?
+* **data** *?boolean* [`false`]: should additional data (node ids for instance) be included in the svg file?
+* **download** *?boolean* [`false`]: should the exporter make the browser download the svg file?
+* **filename** *?string* [`'graph.svg'`]: filename of the file to download.
diff --git a/blogContent/projects/steam/src/plugins/sigma.exporters.svg/sigma.exporters.svg.js b/blogContent/projects/steam/src/plugins/sigma.exporters.svg/sigma.exporters.svg.js
new file mode 100644
index 0000000..58c83e4
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.exporters.svg/sigma.exporters.svg.js
@@ -0,0 +1,225 @@
+;(function(undefined) {
+ 'use strict';
+
+ /**
+ * Sigma SVG Exporter
+ * ===================
+ *
+ * This plugin is designed to export a graph to a svg file that can be
+ * downloaded or just used elsewhere.
+ *
+ * Author: Guillaume Plique (Yomguithereal)
+ * Version: 0.0.1
+ */
+
+ // Terminating if sigma were not to be found
+ if (typeof sigma === 'undefined')
+ throw 'sigma.renderers.snapshot: sigma not in scope.';
+
+
+ /**
+ * Polyfills
+ */
+ var URL = this.URL || this.webkitURL || this;
+
+
+ /**
+ * Utilities
+ */
+ function createBlob(data) {
+ return new Blob(
+ [data],
+ {type: 'image/svg+xml;charset=utf-8'}
+ );
+ }
+
+ function download(string, filename) {
+
+ // Creating blob href
+ var blob = createBlob(string);
+
+ // Anchor
+ var o = {};
+ o.anchor = document.createElement('a');
+ o.anchor.setAttribute('href', URL.createObjectURL(blob));
+ o.anchor.setAttribute('download', filename);
+
+ // Click event
+ var event = document.createEvent('MouseEvent');
+ event.initMouseEvent('click', true, false, window, 0, 0, 0 ,0, 0,
+ false, false, false, false, 0, null);
+
+ URL.revokeObjectURL(blob);
+
+ o.anchor.dispatchEvent(event);
+ delete o.anchor;
+ }
+
+
+ /**
+ * Defaults
+ */
+ var DEFAULTS = {
+ size: '1000',
+ width: '1000',
+ height: '1000',
+ classes: true,
+ labels: true,
+ data: false,
+ download: false,
+ filename: 'graph.svg'
+ };
+
+ var XMLNS = 'http://www.w3.org/2000/svg';
+
+
+ /**
+ * Subprocesses
+ */
+ function optimize(svg, prefix, params) {
+ var nodeColorIndex = {},
+ edgeColorIndex = {},
+ count = 0,
+ color,
+ style,
+ styleText = '',
+ f,
+ i,
+ l;
+
+ // Creating style tag if needed
+ if (params.classes) {
+ style = document.createElementNS(XMLNS, 'style');
+ style.setAttribute('type', 'text/css')
+ svg.insertBefore(style, svg.firstChild);
+ }
+
+ // Iterating over nodes
+ var nodes = svg.querySelectorAll('[id="' + prefix + '-group-nodes"] > [class="' + prefix + '-node"]');
+
+ for (i = 0, l = nodes.length, f = true; i < l; i++) {
+ color = nodes[i].getAttribute('fill');
+
+ if (!params.data)
+ nodes[i].removeAttribute('data-node-id');
+
+ if (params.classes) {
+
+ if (!(color in nodeColorIndex)) {
+ nodeColorIndex[color] = (f ? prefix + '-node' : 'c-' + (count++));
+ styleText += '.' + nodeColorIndex[color] + '{fill: ' + color + '}';
+ }
+
+ if (nodeColorIndex[color] !== prefix + '-node')
+ nodes[i].setAttribute('class', nodes[i].getAttribute('class') + ' ' + nodeColorIndex[color]);
+ nodes[i].removeAttribute('fill');
+ }
+
+ f = false;
+ }
+
+ // Iterating over edges
+ var edges = svg.querySelectorAll('[id="' + prefix + '-group-edges"] > [class="' + prefix + '-edge"]');
+
+ for (i = 0, l = edges.length, f = true; i < l; i++) {
+ color = edges[i].getAttribute('stroke');
+
+ if (!params.data)
+ edges[i].removeAttribute('data-edge-id');
+
+ if (params.classes) {
+
+ if (!(color in edgeColorIndex)) {
+ edgeColorIndex[color] = (f ? prefix + '-edge' : 'c-' + (count++));
+ styleText += '.' + edgeColorIndex[color] + '{stroke: ' + color + '}';
+ }
+
+ if (edgeColorIndex[color] !== prefix + '-edge')
+ edges[i].setAttribute('class', edges[i].getAttribute('class') + ' ' + edgeColorIndex[color]);
+ edges[i].removeAttribute('stroke');
+ }
+
+ f = false;
+ }
+
+ if (params.classes)
+ style.appendChild(document.createTextNode(styleText));
+ }
+
+
+ /**
+ * Extending prototype
+ */
+ sigma.prototype.toSVG = function(params) {
+ params = params || {};
+
+ var prefix = this.settings('classPrefix'),
+ w = params.size || params.width || DEFAULTS.size,
+ h = params.size || params.height || DEFAULTS.size;
+
+ // Creating a dummy container
+ var container = document.createElement('div');
+ container.setAttribute('width', w);
+ container.setAttribute('height', h);
+ container.setAttribute('style', 'position:absolute; top: 0px; left:0px; width: ' + w + 'px; height: ' + h + 'px;');
+
+ // Creating a camera
+ var camera = this.addCamera();
+
+ // Creating a svg renderer
+ var renderer = this.addRenderer({
+ camera: camera,
+ container: container,
+ type: 'svg',
+ forceLabels: !!params.labels
+ });
+
+ // Refreshing
+ renderer.resize(w, h);
+ this.refresh();
+
+ // Dropping camera and renderers before something nasty happens
+ this.killRenderer(renderer);
+ this.killCamera(camera);
+
+ // Retrieving svg
+ var svg = container.querySelector('svg');
+ svg.removeAttribute('style');
+ svg.setAttribute('width', w + 'px');
+ svg.setAttribute('height', h + 'px');
+ svg.setAttribute('x', '0px');
+ svg.setAttribute('y', '0px');
+ // svg.setAttribute('viewBox', '0 0 1000 1000');
+
+ // Dropping labels
+ if (!params.labels) {
+ var labelGroup = svg.querySelector('[id="' + prefix + '-group-labels"]');
+ svg.removeChild(labelGroup);
+ }
+
+ // Dropping hovers
+ var hoverGroup = svg.querySelector('[id="' + prefix + '-group-hovers"]');
+ svg.removeChild(hoverGroup);
+
+ // Optims?
+ params.classes = (params.classes !== false);
+ if (!params.data || params.classes)
+ optimize(svg, prefix, params);
+
+ // Retrieving svg string
+ var svgString = svg.outerHTML;
+
+ // Paranoid cleanup
+ container = null;
+
+ // Output string
+ var output = '\n';
+ output += '\n';
+ output += svgString;
+
+ if (params.download)
+ download(output, params.filename || DEFAULTS.filename);
+
+ return output;
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/Gruntfile.js b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/Gruntfile.js
new file mode 100644
index 0000000..28d60be
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/Gruntfile.js
@@ -0,0 +1,28 @@
+module.exports = function(grunt) {
+
+
+ // Setting grunt base as sigma's root directory
+ grunt.file.setBase('../../');
+
+ // Registering needed files
+ var files = ['supervisor.js', 'worker.js'].map(function(p) {
+ return __dirname + '/' + p;
+ });
+
+ // Project configuration:
+ grunt.initConfig({
+ forceAtlas2: {
+ prod: {
+ files: {
+ 'build/plugins/sigma.layout.forceAtlas2.min.js': files
+ }
+ }
+ }
+ });
+
+ // Loading tasks
+ grunt.loadTasks(__dirname + '/tasks');
+
+ // By default, we will crush and then minify
+ grunt.registerTask('default', ['forceAtlas2:prod']);
+};
diff --git a/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/README.md b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/README.md
new file mode 100644
index 0000000..942e3e3
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/README.md
@@ -0,0 +1,79 @@
+sigma.layout.forceAtlas2
+========================
+
+Algorithm by [Mathieu Jacomy](https://github.com/jacomyma).
+
+Plugin by [Guillaume Plique](https://github.com/Yomguithereal).
+
+---
+
+This plugin implements [ForceAtlas2](http://www.plosone.org/article/info%3Adoi%2F10.1371%2Fjournal.pone.0098679), a force-directed layout algorithm.
+
+For optimization purposes, the algorithm's computations are delegated to a web worker.
+
+## Methods
+
+**sigma.startForceAtlas2**
+
+Starts or unpauses the layout. It is possible to pass a configuration if this is the first time you start the layout.
+
+```js
+sigmaInstance.startForceAtlas2(config);
+```
+
+**sigma.stopForceAtlas2**
+
+Pauses the layout.
+
+```js
+sigmaInstance.stopForceAtlas2();
+```
+
+**sigma.configForceAtlas2**
+
+Changes the layout's configuration.
+
+```js
+sigmaInstance.configForceAtlas2(config);
+```
+
+**sigma.killForceAtlas2**
+
+Completely stops the layout and terminates the assiociated worker. You can still restart it later, but a new worker will have to initialize.
+
+```js
+sigmaInstance.killForceAtlas2();
+```
+
+**sigma.isForceAtlas2Running**
+
+Returns whether ForceAtlas2 is running.
+
+```js
+sigmaInstance.isForceAtlas2Running();
+```
+
+## Configuration
+
+*Algorithm configuration*
+
+* **linLogMode** *boolean* `false`: switch ForceAtlas' model from lin-lin to lin-log (tribute to Andreas Noack). Makes clusters more tight.
+* **outboundAttractionDistribution** *boolean* `false`
+* **adjustSizes** *boolean* `false`
+* **edgeWeightInfluence** *number* `0`: how much influence you give to the edges weight. 0 is "no influence" and 1 is "normal".
+* **scalingRatio** *number* `1`: how much repulsion you want. More makes a more sparse graph.
+* **strongGravityMode** *boolean* `false`
+* **gravity** *number* `1`: attracts nodes to the center. Prevents islands from drifting away.
+* **barnesHutOptimize** *boolean* `true`: should we use the algorithm's Barnes-Hut to improve repulsion's scalability (`O(n²)` to `O(nlog(n))`)? This is useful for large graph but harmful to small ones.
+* **barnesHutTheta** *number* `0.5`
+* **slowDown** *number* `1`
+* **startingIterations** *integer* `1`: number of iterations to be run before the first render.
+* **iterationsPerRender** *integer* `1`: number of iterations to be run before each render.
+
+*Supervisor configuration*
+
+* **worker** *boolean* `true`: should the layout use a web worker?
+* **workerUrl** *string* : path to the worker file if needed because your browser does not support blob workers.
+
+## Notes
+1. The layout won't stop by itself, so if you want it to stop, you will have to trigger it explicitly.
diff --git a/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/supervisor.js b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/supervisor.js
new file mode 100644
index 0000000..57f9b94
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/supervisor.js
@@ -0,0 +1,340 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ /**
+ * Sigma ForceAtlas2.5 Supervisor
+ * ===============================
+ *
+ * Author: Guillaume Plique (Yomguithereal)
+ * Version: 0.1
+ */
+ var _root = this;
+
+ /**
+ * Feature detection
+ * ------------------
+ */
+ var webWorkers = 'Worker' in _root;
+
+ /**
+ * Supervisor Object
+ * ------------------
+ */
+ function Supervisor(sigInst, options) {
+ var _this = this,
+ workerFn = sigInst.getForceAtlas2Worker &&
+ sigInst.getForceAtlas2Worker();
+
+ options = options || {};
+
+ // _root URL Polyfill
+ _root.URL = _root.URL || _root.webkitURL;
+
+ // Properties
+ this.sigInst = sigInst;
+ this.graph = this.sigInst.graph;
+ this.ppn = 10;
+ this.ppe = 3;
+ this.config = {};
+ this.shouldUseWorker =
+ options.worker === false ? false : true && webWorkers;
+ this.workerUrl = options.workerUrl;
+
+ // State
+ this.started = false;
+ this.running = false;
+
+ // Web worker or classic DOM events?
+ if (this.shouldUseWorker) {
+ if (!this.workerUrl) {
+ var blob = this.makeBlob(workerFn);
+ this.worker = new Worker(URL.createObjectURL(blob));
+ }
+ else {
+ this.worker = new Worker(this.workerUrl);
+ }
+
+ // Post Message Polyfill
+ this.worker.postMessage =
+ this.worker.webkitPostMessage || this.worker.postMessage;
+ }
+ else {
+
+ eval(workerFn);
+ }
+
+ // Worker message receiver
+ this.msgName = (this.worker) ? 'message' : 'newCoords';
+ this.listener = function(e) {
+
+ // Retrieving data
+ _this.nodesByteArray = new Float32Array(e.data.nodes);
+
+ // If ForceAtlas2 is running, we act accordingly
+ if (_this.running) {
+
+ // Applying layout
+ _this.applyLayoutChanges();
+
+ // Send data back to worker and loop
+ _this.sendByteArrayToWorker();
+
+ // Rendering graph
+ _this.sigInst.refresh();
+ }
+ };
+
+ (this.worker || document).addEventListener(this.msgName, this.listener);
+
+ // Filling byteArrays
+ this.graphToByteArrays();
+
+ // Binding on kill to properly terminate layout when parent is killed
+ sigInst.bind('kill', function() {
+ sigInst.killForceAtlas2();
+ });
+ }
+
+ Supervisor.prototype.makeBlob = function(workerFn) {
+ var blob;
+
+ try {
+ blob = new Blob([workerFn], {type: 'application/javascript'});
+ }
+ catch (e) {
+ _root.BlobBuilder = _root.BlobBuilder ||
+ _root.WebKitBlobBuilder ||
+ _root.MozBlobBuilder;
+
+ blob = new BlobBuilder();
+ blob.append(workerFn);
+ blob = blob.getBlob();
+ }
+
+ return blob;
+ };
+
+ Supervisor.prototype.graphToByteArrays = function() {
+ var nodes = this.graph.nodes(),
+ edges = this.graph.edges(),
+ nbytes = nodes.length * this.ppn,
+ ebytes = edges.length * this.ppe,
+ nIndex = {},
+ i,
+ j,
+ l;
+
+ // Allocating Byte arrays with correct nb of bytes
+ this.nodesByteArray = new Float32Array(nbytes);
+ this.edgesByteArray = new Float32Array(ebytes);
+
+ // Iterate through nodes
+ for (i = j = 0, l = nodes.length; i < l; i++) {
+
+ // Populating index
+ nIndex[nodes[i].id] = j;
+
+ // Populating byte array
+ this.nodesByteArray[j] = nodes[i].x;
+ this.nodesByteArray[j + 1] = nodes[i].y;
+ this.nodesByteArray[j + 2] = 0;
+ this.nodesByteArray[j + 3] = 0;
+ this.nodesByteArray[j + 4] = 0;
+ this.nodesByteArray[j + 5] = 0;
+ this.nodesByteArray[j + 6] = 1 + this.graph.degree(nodes[i].id);
+ this.nodesByteArray[j + 7] = 1;
+ this.nodesByteArray[j + 8] = nodes[i].size;
+ this.nodesByteArray[j + 9] = 0;
+ j += this.ppn;
+ }
+
+ // Iterate through edges
+ for (i = j = 0, l = edges.length; i < l; i++) {
+ this.edgesByteArray[j] = nIndex[edges[i].source];
+ this.edgesByteArray[j + 1] = nIndex[edges[i].target];
+ this.edgesByteArray[j + 2] = edges[i].weight || 0;
+ j += this.ppe;
+ }
+ };
+
+ // TODO: make a better send function
+ Supervisor.prototype.applyLayoutChanges = function() {
+ var nodes = this.graph.nodes(),
+ j = 0,
+ realIndex;
+
+ // Moving nodes
+ for (var i = 0, l = this.nodesByteArray.length; i < l; i += this.ppn) {
+ nodes[j].x = this.nodesByteArray[i];
+ nodes[j].y = this.nodesByteArray[i + 1];
+ j++;
+ }
+ };
+
+ Supervisor.prototype.sendByteArrayToWorker = function(action) {
+ var content = {
+ action: action || 'loop',
+ nodes: this.nodesByteArray.buffer
+ };
+
+ var buffers = [this.nodesByteArray.buffer];
+
+ if (action === 'start') {
+ content.config = this.config || {};
+ content.edges = this.edgesByteArray.buffer;
+ buffers.push(this.edgesByteArray.buffer);
+ }
+
+ if (this.shouldUseWorker)
+ this.worker.postMessage(content, buffers);
+ else
+ _root.postMessage(content, '*');
+ };
+
+ Supervisor.prototype.start = function() {
+ if (this.running)
+ return;
+
+ this.running = true;
+
+ // Do not refresh edgequadtree during layout:
+ var k,
+ c;
+ for (k in this.sigInst.cameras) {
+ c = this.sigInst.cameras[k];
+ c.edgequadtree._enabled = false;
+ }
+
+ if (!this.started) {
+
+ // Sending init message to worker
+ this.sendByteArrayToWorker('start');
+ this.started = true;
+ }
+ else {
+ this.sendByteArrayToWorker();
+ }
+ };
+
+ Supervisor.prototype.stop = function() {
+ if (!this.running)
+ return;
+
+ // Allow to refresh edgequadtree:
+ var k,
+ c,
+ bounds;
+ for (k in this.sigInst.cameras) {
+ c = this.sigInst.cameras[k];
+ c.edgequadtree._enabled = true;
+
+ // Find graph boundaries:
+ bounds = sigma.utils.getBoundaries(
+ this.graph,
+ c.readPrefix
+ );
+
+ // Refresh edgequadtree:
+ if (c.settings('drawEdges') && c.settings('enableEdgeHovering'))
+ c.edgequadtree.index(this.sigInst.graph, {
+ prefix: c.readPrefix,
+ bounds: {
+ x: bounds.minX,
+ y: bounds.minY,
+ width: bounds.maxX - bounds.minX,
+ height: bounds.maxY - bounds.minY
+ }
+ });
+ }
+
+ this.running = false;
+ };
+
+ Supervisor.prototype.killWorker = function() {
+ if (this.worker) {
+ this.worker.terminate();
+ }
+ else {
+ _root.postMessage({action: 'kill'}, '*');
+ document.removeEventListener(this.msgName, this.listener);
+ }
+ };
+
+ Supervisor.prototype.configure = function(config) {
+
+ // Setting configuration
+ this.config = config;
+
+ if (!this.started)
+ return;
+
+ var data = {action: 'config', config: this.config};
+
+ if (this.shouldUseWorker)
+ this.worker.postMessage(data);
+ else
+ _root.postMessage(data, '*');
+ };
+
+ /**
+ * Interface
+ * ----------
+ */
+ sigma.prototype.startForceAtlas2 = function(config) {
+
+ // Create supervisor if undefined
+ if (!this.supervisor)
+ this.supervisor = new Supervisor(this, config);
+
+ // Configuration provided?
+ if (config)
+ this.supervisor.configure(config);
+
+ // Start algorithm
+ this.supervisor.start();
+
+ return this;
+ };
+
+ sigma.prototype.stopForceAtlas2 = function() {
+ if (!this.supervisor)
+ return this;
+
+ // Pause algorithm
+ this.supervisor.stop();
+
+ return this;
+ };
+
+ sigma.prototype.killForceAtlas2 = function() {
+ if (!this.supervisor)
+ return this;
+
+ // Stop Algorithm
+ this.supervisor.stop();
+
+ // Kill Worker
+ this.supervisor.killWorker();
+
+ // Kill supervisor
+ this.supervisor = null;
+
+ return this;
+ };
+
+ sigma.prototype.configForceAtlas2 = function(config) {
+ if (!this.supervisor)
+ this.supervisor = new Supervisor(this, config);
+
+ this.supervisor.configure(config);
+
+ return this;
+ };
+
+ sigma.prototype.isForceAtlas2Running = function(config) {
+ return !!this.supervisor && this.supervisor.running;
+ };
+}).call(this);
diff --git a/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/tasks/forceAtlas2.js b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/tasks/forceAtlas2.js
new file mode 100644
index 0000000..1bb0062
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/tasks/forceAtlas2.js
@@ -0,0 +1,127 @@
+/*
+ * grunt-forceAtlas2
+ *
+ * This task crush and minify Force Atlas 2 code.
+ */
+var uglify = require('uglify-js');
+
+// Shorteners
+function minify(string) {
+ return uglify.minify(string, {fromString: true}).code;
+}
+
+// Crushing function
+function crush(fnString) {
+ var pattern,
+ i,
+ l;
+
+ var np = [
+ 'x',
+ 'y',
+ 'dx',
+ 'dy',
+ 'old_dx',
+ 'old_dy',
+ 'mass',
+ 'convergence',
+ 'size',
+ 'fixed'
+ ];
+
+ var ep = [
+ 'source',
+ 'target',
+ 'weight'
+ ];
+
+ var rp = [
+ 'node',
+ 'centerX',
+ 'centerY',
+ 'size',
+ 'nextSibling',
+ 'firstChild',
+ 'mass',
+ 'massCenterX',
+ 'massCenterY'
+ ];
+
+ // Replacing matrix accessors by incremented indexes
+ for (i = 0, l = rp.length; i < l; i++) {
+ pattern = new RegExp('rp\\(([^,]*), \'' + rp[i] + '\'\\)', 'g');
+ fnString = fnString.replace(
+ pattern,
+ (i === 0) ? '$1' : '$1 + ' + i
+ );
+ }
+
+ for (i = 0, l = np.length; i < l; i++) {
+ pattern = new RegExp('np\\(([^,]*), \'' + np[i] + '\'\\)', 'g');
+ fnString = fnString.replace(
+ pattern,
+ (i === 0) ? '$1' : '$1 + ' + i
+ );
+ }
+
+ for (i = 0, l = ep.length; i < l; i++) {
+ pattern = new RegExp('ep\\(([^,]*), \'' + ep[i] + '\'\\)', 'g');
+ fnString = fnString.replace(
+ pattern,
+ (i === 0) ? '$1' : '$1 + ' + i
+ );
+ }
+
+ return fnString;
+}
+
+// Cleaning function
+function clean(string) {
+ return string.replace(
+ /function crush\(fnString\)/,
+ 'var crush = null; function no_crush(fnString)'
+ );
+}
+
+module.exports = function(grunt) {
+
+ // Force atlas grunt multitask
+ function multitask() {
+
+ // Merge task-specific and/or target-specific options with these defaults.
+ var options = this.options({});
+
+ // Iterate over all specified file groups.
+ this.files.forEach(function(f) {
+ // Concat specified files.
+ var src = f.src.filter(function(filepath) {
+ // Warn on and remove invalid source files (if nonull was set).
+ if (!grunt.file.exists(filepath)) {
+ grunt.log.warn('Source file "' + filepath + '" not found.');
+ return false;
+ } else {
+ return true;
+ }
+ }).map(function(filepath) {
+ // Read file source.
+ return grunt.file.read(filepath);
+ }).join('\n');
+
+ // Crushing, cleaning and minifying
+ src = minify(clean(crush(src)));
+
+ // Write the destination file.
+ grunt.file.write(f.dest, src);
+
+ // Print a success message.
+ grunt.log.writeln('File "' + f.dest + '" created.');
+ });
+ }
+
+ // Registering the task
+ grunt.registerMultiTask(
+ 'forceAtlas2',
+ 'A grunt task to crush and minify ForceAtlas2.',
+ multitask
+ );
+};
diff --git a/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/worker.js b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/worker.js
new file mode 100644
index 0000000..adc0b29
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.layout.forceAtlas2/worker.js
@@ -0,0 +1,1129 @@
+;(function(undefined) {
+ 'use strict';
+
+ /**
+ * Sigma ForceAtlas2.5 Webworker
+ * ==============================
+ *
+ * Author: Guillaume Plique (Yomguithereal)
+ * Algorithm author: Mathieu Jacomy @ Sciences Po Medialab & WebAtlas
+ * Version: 1.0.3
+ */
+
+ var _root = this,
+ inWebWorker = !('document' in _root);
+
+ /**
+ * Worker Function Wrapper
+ * ------------------------
+ *
+ * The worker has to be wrapped into a single stringified function
+ * to be passed afterwards as a BLOB object to the supervisor.
+ */
+ var Worker = function(undefined) {
+ 'use strict';
+
+ /**
+ * Worker settings and properties
+ */
+ var W = {
+
+ // Properties
+ ppn: 10,
+ ppe: 3,
+ ppr: 9,
+ maxForce: 10,
+ iterations: 0,
+ converged: false,
+
+ // Possible to change through config
+ settings: {
+ linLogMode: false,
+ outboundAttractionDistribution: false,
+ adjustSizes: false,
+ edgeWeightInfluence: 0,
+ scalingRatio: 1,
+ strongGravityMode: false,
+ gravity: 1,
+ slowDown: 1,
+ barnesHutOptimize: false,
+ barnesHutTheta: 0.5,
+ startingIterations: 1,
+ iterationsPerRender: 1
+ }
+ };
+
+ var NodeMatrix,
+ EdgeMatrix,
+ RegionMatrix;
+
+ /**
+ * Helpers
+ */
+ function extend() {
+ var i,
+ k,
+ res = {},
+ l = arguments.length;
+
+ for (i = l - 1; i >= 0; i--)
+ for (k in arguments[i])
+ res[k] = arguments[i][k];
+ return res;
+ }
+
+ function __emptyObject(obj) {
+ var k;
+
+ for (k in obj)
+ if (!('hasOwnProperty' in obj) || obj.hasOwnProperty(k))
+ delete obj[k];
+
+ return obj;
+ }
+
+ /**
+ * Matrices properties accessors
+ */
+ var nodeProperties = {
+ x: 0,
+ y: 1,
+ dx: 2,
+ dy: 3,
+ old_dx: 4,
+ old_dy: 5,
+ mass: 6,
+ convergence: 7,
+ size: 8,
+ fixed: 9
+ };
+
+ var edgeProperties = {
+ source: 0,
+ target: 1,
+ weight: 2
+ };
+
+ var regionProperties = {
+ node: 0,
+ centerX: 1,
+ centerY: 2,
+ size: 3,
+ nextSibling: 4,
+ firstChild: 5,
+ mass: 6,
+ massCenterX: 7,
+ massCenterY: 8
+ };
+
+ function np(i, p) {
+
+ // DEBUG: safeguards
+ if ((i % W.ppn) !== 0)
+ throw 'np: non correct (' + i + ').';
+ if (i !== parseInt(i))
+ throw 'np: non int.';
+
+ if (p in nodeProperties)
+ return i + nodeProperties[p];
+ else
+ throw 'ForceAtlas2.Worker - ' +
+ 'Inexistant node property given (' + p + ').';
+ }
+
+ function ep(i, p) {
+
+ // DEBUG: safeguards
+ if ((i % W.ppe) !== 0)
+ throw 'ep: non correct (' + i + ').';
+ if (i !== parseInt(i))
+ throw 'ep: non int.';
+
+ if (p in edgeProperties)
+ return i + edgeProperties[p];
+ else
+ throw 'ForceAtlas2.Worker - ' +
+ 'Inexistant edge property given (' + p + ').';
+ }
+
+ function rp(i, p) {
+
+ // DEBUG: safeguards
+ if ((i % W.ppr) !== 0)
+ throw 'rp: non correct (' + i + ').';
+ if (i !== parseInt(i))
+ throw 'rp: non int.';
+
+ if (p in regionProperties)
+ return i + regionProperties[p];
+ else
+ throw 'ForceAtlas2.Worker - ' +
+ 'Inexistant region property given (' + p + ').';
+ }
+
+ // DEBUG
+ function nan(v) {
+ if (isNaN(v))
+ throw 'NaN alert!';
+ }
+
+
+ /**
+ * Algorithm initialization
+ */
+
+ function init(nodes, edges, config) {
+ config = config || {};
+ var i, l;
+
+ // Matrices
+ NodeMatrix = nodes;
+ EdgeMatrix = edges;
+
+ // Length
+ W.nodesLength = NodeMatrix.length;
+ W.edgesLength = EdgeMatrix.length;
+
+ // Merging configuration
+ configure(config);
+ }
+
+ function configure(o) {
+ W.settings = extend(o, W.settings);
+ }
+
+ /**
+ * Algorithm pass
+ */
+
+ // MATH: get distances stuff and power 2 issues
+ function pass() {
+ var a, i, j, l, r, n, n1, n2, e, w, g, k, m;
+
+ var outboundAttCompensation,
+ coefficient,
+ xDist,
+ yDist,
+ ewc,
+ mass,
+ distance,
+ size,
+ factor;
+
+ // 1) Initializing layout data
+ //-----------------------------
+
+ // Resetting positions & computing max values
+ for (n = 0; n < W.nodesLength; n += W.ppn) {
+ NodeMatrix[np(n, 'old_dx')] = NodeMatrix[np(n, 'dx')];
+ NodeMatrix[np(n, 'old_dy')] = NodeMatrix[np(n, 'dy')];
+ NodeMatrix[np(n, 'dx')] = 0;
+ NodeMatrix[np(n, 'dy')] = 0;
+ }
+
+ // If outbound attraction distribution, compensate
+ if (W.settings.outboundAttractionDistribution) {
+ outboundAttCompensation = 0;
+ for (n = 0; n < W.nodesLength; n += W.ppn) {
+ outboundAttCompensation += NodeMatrix[np(n, 'mass')];
+ }
+
+ outboundAttCompensation /= W.nodesLength;
+ }
+
+
+ // 1.bis) Barnes-Hut computation
+ //------------------------------
+
+ if (W.settings.barnesHutOptimize) {
+
+ var minX = Infinity,
+ maxX = -Infinity,
+ minY = Infinity,
+ maxY = -Infinity,
+ q, q0, q1, q2, q3;
+
+ // Setting up
+ // RegionMatrix = new Float32Array(W.nodesLength / W.ppn * 4 * W.ppr);
+ RegionMatrix = [];
+
+ // Computing min and max values
+ for (n = 0; n < W.nodesLength; n += W.ppn) {
+ minX = Math.min(minX, NodeMatrix[np(n, 'x')]);
+ maxX = Math.max(maxX, NodeMatrix[np(n, 'x')]);
+ minY = Math.min(minY, NodeMatrix[np(n, 'y')]);
+ maxY = Math.max(maxY, NodeMatrix[np(n, 'y')]);
+ }
+
+ // Build the Barnes Hut root region
+ RegionMatrix[rp(0, 'node')] = -1;
+ RegionMatrix[rp(0, 'centerX')] = (minX + maxX) / 2;
+ RegionMatrix[rp(0, 'centerY')] = (minY + maxY) / 2;
+ RegionMatrix[rp(0, 'size')] = Math.max(maxX - minX, maxY - minY);
+ RegionMatrix[rp(0, 'nextSibling')] = -1;
+ RegionMatrix[rp(0, 'firstChild')] = -1;
+ RegionMatrix[rp(0, 'mass')] = 0;
+ RegionMatrix[rp(0, 'massCenterX')] = 0;
+ RegionMatrix[rp(0, 'massCenterY')] = 0;
+
+ // Add each node in the tree
+ l = 1;
+ for (n = 0; n < W.nodesLength; n += W.ppn) {
+
+ // Current region, starting with root
+ r = 0;
+
+ while (true) {
+ // Are there sub-regions?
+
+ // We look at first child index
+ if (RegionMatrix[rp(r, 'firstChild')] >= 0) {
+
+ // There are sub-regions
+
+ // We just iterate to find a "leave" of the tree
+ // that is an empty region or a region with a single node
+ // (see next case)
+
+ // Find the quadrant of n
+ if (NodeMatrix[np(n, 'x')] < RegionMatrix[rp(r, 'centerX')]) {
+
+ if (NodeMatrix[np(n, 'y')] < RegionMatrix[rp(r, 'centerY')]) {
+
+ // Top Left quarter
+ q = RegionMatrix[rp(r, 'firstChild')];
+ }
+ else {
+
+ // Bottom Left quarter
+ q = RegionMatrix[rp(r, 'firstChild')] + W.ppr;
+ }
+ }
+ else {
+ if (NodeMatrix[np(n, 'y')] < RegionMatrix[rp(r, 'centerY')]) {
+
+ // Top Right quarter
+ q = RegionMatrix[rp(r, 'firstChild')] + W.ppr * 2;
+ }
+ else {
+
+ // Bottom Right quarter
+ q = RegionMatrix[rp(r, 'firstChild')] + W.ppr * 3;
+ }
+ }
+
+ // Update center of mass and mass (we only do it for non-leave regions)
+ RegionMatrix[rp(r, 'massCenterX')] =
+ (RegionMatrix[rp(r, 'massCenterX')] * RegionMatrix[rp(r, 'mass')] +
+ NodeMatrix[np(n, 'x')] * NodeMatrix[np(n, 'mass')]) /
+ (RegionMatrix[rp(r, 'mass')] + NodeMatrix[np(n, 'mass')]);
+
+ RegionMatrix[rp(r, 'massCenterY')] =
+ (RegionMatrix[rp(r, 'massCenterY')] * RegionMatrix[rp(r, 'mass')] +
+ NodeMatrix[np(n, 'y')] * NodeMatrix[np(n, 'mass')]) /
+ (RegionMatrix[rp(r, 'mass')] + NodeMatrix[np(n, 'mass')]);
+
+ RegionMatrix[rp(r, 'mass')] += NodeMatrix[np(n, 'mass')];
+
+ // Iterate on the right quadrant
+ r = q;
+ continue;
+ }
+ else {
+
+ // There are no sub-regions: we are in a "leave"
+
+ // Is there a node in this leave?
+ if (RegionMatrix[rp(r, 'node')] < 0) {
+
+ // There is no node in region:
+ // we record node n and go on
+ RegionMatrix[rp(r, 'node')] = n;
+ break;
+ }
+ else {
+
+ // There is a node in this region
+
+ // We will need to create sub-regions, stick the two
+ // nodes (the old one r[0] and the new one n) in two
+ // subregions. If they fall in the same quadrant,
+ // we will iterate.
+
+ // Create sub-regions
+ RegionMatrix[rp(r, 'firstChild')] = l * W.ppr;
+ w = RegionMatrix[rp(r, 'size')] / 2; // new size (half)
+
+ // NOTE: we use screen coordinates
+ // from Top Left to Bottom Right
+
+ // Top Left sub-region
+ g = RegionMatrix[rp(r, 'firstChild')];
+
+ RegionMatrix[rp(g, 'node')] = -1;
+ RegionMatrix[rp(g, 'centerX')] = RegionMatrix[rp(r, 'centerX')] - w;
+ RegionMatrix[rp(g, 'centerY')] = RegionMatrix[rp(r, 'centerY')] - w;
+ RegionMatrix[rp(g, 'size')] = w;
+ RegionMatrix[rp(g, 'nextSibling')] = g + W.ppr;
+ RegionMatrix[rp(g, 'firstChild')] = -1;
+ RegionMatrix[rp(g, 'mass')] = 0;
+ RegionMatrix[rp(g, 'massCenterX')] = 0;
+ RegionMatrix[rp(g, 'massCenterY')] = 0;
+
+ // Bottom Left sub-region
+ g += W.ppr;
+ RegionMatrix[rp(g, 'node')] = -1;
+ RegionMatrix[rp(g, 'centerX')] = RegionMatrix[rp(r, 'centerX')] - w;
+ RegionMatrix[rp(g, 'centerY')] = RegionMatrix[rp(r, 'centerY')] + w;
+ RegionMatrix[rp(g, 'size')] = w;
+ RegionMatrix[rp(g, 'nextSibling')] = g + W.ppr;
+ RegionMatrix[rp(g, 'firstChild')] = -1;
+ RegionMatrix[rp(g, 'mass')] = 0;
+ RegionMatrix[rp(g, 'massCenterX')] = 0;
+ RegionMatrix[rp(g, 'massCenterY')] = 0;
+
+ // Top Right sub-region
+ g += W.ppr;
+ RegionMatrix[rp(g, 'node')] = -1;
+ RegionMatrix[rp(g, 'centerX')] = RegionMatrix[rp(r, 'centerX')] + w;
+ RegionMatrix[rp(g, 'centerY')] = RegionMatrix[rp(r, 'centerY')] - w;
+ RegionMatrix[rp(g, 'size')] = w;
+ RegionMatrix[rp(g, 'nextSibling')] = g + W.ppr;
+ RegionMatrix[rp(g, 'firstChild')] = -1;
+ RegionMatrix[rp(g, 'mass')] = 0;
+ RegionMatrix[rp(g, 'massCenterX')] = 0;
+ RegionMatrix[rp(g, 'massCenterY')] = 0;
+
+ // Bottom Right sub-region
+ g += W.ppr;
+ RegionMatrix[rp(g, 'node')] = -1;
+ RegionMatrix[rp(g, 'centerX')] = RegionMatrix[rp(r, 'centerX')] + w;
+ RegionMatrix[rp(g, 'centerY')] = RegionMatrix[rp(r, 'centerY')] + w;
+ RegionMatrix[rp(g, 'size')] = w;
+ RegionMatrix[rp(g, 'nextSibling')] = RegionMatrix[rp(r, 'nextSibling')];
+ RegionMatrix[rp(g, 'firstChild')] = -1;
+ RegionMatrix[rp(g, 'mass')] = 0;
+ RegionMatrix[rp(g, 'massCenterX')] = 0;
+ RegionMatrix[rp(g, 'massCenterY')] = 0;
+
+ l += 4;
+
+ // Now the goal is to find two different sub-regions
+ // for the two nodes: the one previously recorded (r[0])
+ // and the one we want to add (n)
+
+ // Find the quadrant of the old node
+ if (NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'x')] < RegionMatrix[rp(r, 'centerX')]) {
+ if (NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'y')] < RegionMatrix[rp(r, 'centerY')]) {
+
+ // Top Left quarter
+ q = RegionMatrix[rp(r, 'firstChild')];
+ }
+ else {
+
+ // Bottom Left quarter
+ q = RegionMatrix[rp(r, 'firstChild')] + W.ppr;
+ }
+ }
+ else {
+ if (NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'y')] < RegionMatrix[rp(r, 'centerY')]) {
+
+ // Top Right quarter
+ q = RegionMatrix[rp(r, 'firstChild')] + W.ppr * 2;
+ }
+ else {
+
+ // Bottom Right quarter
+ q = RegionMatrix[rp(r, 'firstChild')] + W.ppr * 3;
+ }
+ }
+
+ // We remove r[0] from the region r, add its mass to r and record it in q
+ RegionMatrix[rp(r, 'mass')] = NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'mass')];
+ RegionMatrix[rp(r, 'massCenterX')] = NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'x')];
+ RegionMatrix[rp(r, 'massCenterY')] = NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'y')];
+
+ RegionMatrix[rp(q, 'node')] = RegionMatrix[rp(r, 'node')];
+ RegionMatrix[rp(r, 'node')] = -1;
+
+ // Find the quadrant of n
+ if (NodeMatrix[np(n, 'x')] < RegionMatrix[rp(r, 'centerX')]) {
+ if (NodeMatrix[np(n, 'y')] < RegionMatrix[rp(r, 'centerY')]) {
+
+ // Top Left quarter
+ q2 = RegionMatrix[rp(r, 'firstChild')];
+ }
+ else {
+ // Bottom Left quarter
+ q2 = RegionMatrix[rp(r, 'firstChild')] + W.ppr;
+ }
+ }
+ else {
+ if(NodeMatrix[np(n, 'y')] < RegionMatrix[rp(r, 'centerY')]) {
+
+ // Top Right quarter
+ q2 = RegionMatrix[rp(r, 'firstChild')] + W.ppr * 2;
+ }
+ else {
+
+ // Bottom Right quarter
+ q2 = RegionMatrix[rp(r, 'firstChild')] + W.ppr * 3;
+ }
+ }
+
+ if (q === q2) {
+
+ // If both nodes are in the same quadrant,
+ // we have to try it again on this quadrant
+ r = q;
+ continue;
+ }
+
+ // If both quadrants are different, we record n
+ // in its quadrant
+ RegionMatrix[rp(q2, 'node')] = n;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+ // 2) Repulsion
+ //--------------
+ // NOTES: adjustSizes = antiCollision & scalingRatio = coefficient
+
+ if (W.settings.barnesHutOptimize) {
+ coefficient = W.settings.scalingRatio;
+
+ // Applying repulsion through regions
+ for (n = 0; n < W.nodesLength; n += W.ppn) {
+
+ // Computing leaf quad nodes iteration
+
+ r = 0; // Starting with root region
+ while (true) {
+
+ if (RegionMatrix[rp(r, 'firstChild')] >= 0) {
+
+ // The region has sub-regions
+
+ // We run the Barnes Hut test to see if we are at the right distance
+ distance = Math.sqrt(
+ (Math.pow(NodeMatrix[np(n, 'x')] - RegionMatrix[rp(r, 'massCenterX')], 2)) +
+ (Math.pow(NodeMatrix[np(n, 'y')] - RegionMatrix[rp(r, 'massCenterY')], 2))
+ );
+
+ if (2 * RegionMatrix[rp(r, 'size')] / distance < W.settings.barnesHutTheta) {
+
+ // We treat the region as a single body, and we repulse
+
+ xDist = NodeMatrix[np(n, 'x')] - RegionMatrix[rp(r, 'massCenterX')];
+ yDist = NodeMatrix[np(n, 'y')] - RegionMatrix[rp(r, 'massCenterY')];
+
+ if (W.settings.adjustSizes) {
+
+ //-- Linear Anti-collision Repulsion
+ if (distance > 0) {
+ factor = coefficient * NodeMatrix[np(n, 'mass')] *
+ RegionMatrix[rp(r, 'mass')] / distance / distance;
+
+ NodeMatrix[np(n, 'dx')] += xDist * factor;
+ NodeMatrix[np(n, 'dy')] += yDist * factor;
+ }
+ else if (distance < 0) {
+ factor = -coefficient * NodeMatrix[np(n, 'mass')] *
+ RegionMatrix[rp(r, 'mass')] / distance;
+
+ NodeMatrix[np(n, 'dx')] += xDist * factor;
+ NodeMatrix[np(n, 'dy')] += yDist * factor;
+ }
+ }
+ else {
+
+ //-- Linear Repulsion
+ if (distance > 0) {
+ factor = coefficient * NodeMatrix[np(n, 'mass')] *
+ RegionMatrix[rp(r, 'mass')] / distance / distance;
+
+ NodeMatrix[np(n, 'dx')] += xDist * factor;
+ NodeMatrix[np(n, 'dy')] += yDist * factor;
+ }
+ }
+
+ // When this is done, we iterate. We have to look at the next sibling.
+ if (RegionMatrix[rp(r, 'nextSibling')] < 0)
+ break; // No next sibling: we have finished the tree
+ r = RegionMatrix[rp(r, 'nextSibling')];
+ continue;
+
+ }
+ else {
+
+ // The region is too close and we have to look at sub-regions
+ r = RegionMatrix[rp(r, 'firstChild')];
+ continue;
+ }
+
+ }
+ else {
+
+ // The region has no sub-region
+ // If there is a node r[0] and it is not n, then repulse
+
+ if (RegionMatrix[rp(r, 'node')] >= 0 && RegionMatrix[rp(r, 'node')] !== n) {
+ xDist = NodeMatrix[np(n, 'x')] - NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'x')];
+ yDist = NodeMatrix[np(n, 'y')] - NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'y')];
+
+ distance = Math.sqrt(xDist * xDist + yDist * yDist);
+
+ if (W.settings.adjustSizes) {
+
+ //-- Linear Anti-collision Repulsion
+ if (distance > 0) {
+ factor = coefficient * NodeMatrix[np(n, 'mass')] *
+ NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'mass')] / distance / distance;
+
+ NodeMatrix[np(n, 'dx')] += xDist * factor;
+ NodeMatrix[np(n, 'dy')] += yDist * factor;
+ }
+ else if (distance < 0) {
+ factor = -coefficient * NodeMatrix[np(n, 'mass')] *
+ NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'mass')] / distance;
+
+ NodeMatrix[np(n, 'dx')] += xDist * factor;
+ NodeMatrix[np(n, 'dy')] += yDist * factor;
+ }
+ }
+ else {
+
+ //-- Linear Repulsion
+ if (distance > 0) {
+ factor = coefficient * NodeMatrix[np(n, 'mass')] *
+ NodeMatrix[np(RegionMatrix[rp(r, 'node')], 'mass')] / distance / distance;
+
+ NodeMatrix[np(n, 'dx')] += xDist * factor;
+ NodeMatrix[np(n, 'dy')] += yDist * factor;
+ }
+ }
+
+ }
+
+ // When this is done, we iterate. We have to look at the next sibling.
+ if (RegionMatrix[rp(r, 'nextSibling')] < 0)
+ break; // No next sibling: we have finished the tree
+ r = RegionMatrix[rp(r, 'nextSibling')];
+ continue;
+ }
+ }
+ }
+ }
+ else {
+ coefficient = W.settings.scalingRatio;
+
+ // Square iteration
+ for (n1 = 0; n1 < W.nodesLength; n1 += W.ppn) {
+ for (n2 = 0; n2 < n1; n2 += W.ppn) {
+
+ // Common to both methods
+ xDist = NodeMatrix[np(n1, 'x')] - NodeMatrix[np(n2, 'x')];
+ yDist = NodeMatrix[np(n1, 'y')] - NodeMatrix[np(n2, 'y')];
+
+ if (W.settings.adjustSizes) {
+
+ //-- Anticollision Linear Repulsion
+ distance = Math.sqrt(xDist * xDist + yDist * yDist) -
+ NodeMatrix[np(n1, 'size')] -
+ NodeMatrix[np(n2, 'size')];
+
+ if (distance > 0) {
+ factor = coefficient *
+ NodeMatrix[np(n1, 'mass')] *
+ NodeMatrix[np(n2, 'mass')] /
+ distance / distance;
+
+ // Updating nodes' dx and dy
+ NodeMatrix[np(n1, 'dx')] += xDist * factor;
+ NodeMatrix[np(n1, 'dy')] += yDist * factor;
+
+ NodeMatrix[np(n2, 'dx')] += xDist * factor;
+ NodeMatrix[np(n2, 'dy')] += yDist * factor;
+ }
+ else if (distance < 0) {
+ factor = 100 * coefficient *
+ NodeMatrix[np(n1, 'mass')] *
+ NodeMatrix[np(n2, 'mass')];
+
+ // Updating nodes' dx and dy
+ NodeMatrix[np(n1, 'dx')] += xDist * factor;
+ NodeMatrix[np(n1, 'dy')] += yDist * factor;
+
+ NodeMatrix[np(n2, 'dx')] -= xDist * factor;
+ NodeMatrix[np(n2, 'dy')] -= yDist * factor;
+ }
+ }
+ else {
+
+ //-- Linear Repulsion
+ distance = Math.sqrt(xDist * xDist + yDist * yDist);
+
+ if (distance > 0) {
+ factor = coefficient *
+ NodeMatrix[np(n1, 'mass')] *
+ NodeMatrix[np(n2, 'mass')] /
+ distance / distance;
+
+ // Updating nodes' dx and dy
+ NodeMatrix[np(n1, 'dx')] += xDist * factor;
+ NodeMatrix[np(n1, 'dy')] += yDist * factor;
+
+ NodeMatrix[np(n2, 'dx')] -= xDist * factor;
+ NodeMatrix[np(n2, 'dy')] -= yDist * factor;
+ }
+ }
+ }
+ }
+ }
+
+
+ // 3) Gravity
+ //------------
+ g = W.settings.gravity / W.settings.scalingRatio;
+ coefficient = W.settings.scalingRatio;
+ for (n = 0; n < W.nodesLength; n += W.ppn) {
+ factor = 0;
+
+ // Common to both methods
+ xDist = NodeMatrix[np(n, 'x')];
+ yDist = NodeMatrix[np(n, 'y')];
+ distance = Math.sqrt(
+ Math.pow(xDist, 2) + Math.pow(yDist, 2)
+ );
+
+ if (W.settings.strongGravityMode) {
+
+ //-- Strong gravity
+ if (distance > 0)
+ factor = coefficient * NodeMatrix[np(n, 'mass')] * g;
+ }
+ else {
+
+ //-- Linear Anti-collision Repulsion n
+ if (distance > 0)
+ factor = coefficient * NodeMatrix[np(n, 'mass')] * g / distance;
+ }
+
+ // Updating node's dx and dy
+ NodeMatrix[np(n, 'dx')] -= xDist * factor;
+ NodeMatrix[np(n, 'dy')] -= yDist * factor;
+ }
+
+
+
+ // 4) Attraction
+ //---------------
+ coefficient = 1 *
+ (W.settings.outboundAttractionDistribution ?
+ outboundAttCompensation :
+ 1);
+
+ // TODO: simplify distance
+ // TODO: coefficient is always used as -c --> optimize?
+ for (e = 0; e < W.edgesLength; e += W.ppe) {
+ n1 = EdgeMatrix[ep(e, 'source')];
+ n2 = EdgeMatrix[ep(e, 'target')];
+ w = EdgeMatrix[ep(e, 'weight')];
+
+ // Edge weight influence
+ ewc = Math.pow(w, W.settings.edgeWeightInfluence);
+
+ // Common measures
+ xDist = NodeMatrix[np(n1, 'x')] - NodeMatrix[np(n2, 'x')];
+ yDist = NodeMatrix[np(n1, 'y')] - NodeMatrix[np(n2, 'y')];
+
+ // Applying attraction to nodes
+ if (W.settings.adjustSizes) {
+
+ distance = Math.sqrt(
+ (Math.pow(xDist, 2) + Math.pow(yDist, 2)) -
+ NodeMatrix[np(n1, 'size')] -
+ NodeMatrix[np(n2, 'size')]
+ );
+
+ if (W.settings.linLogMode) {
+ if (W.settings.outboundAttractionDistribution) {
+
+ //-- LinLog Degree Distributed Anti-collision Attraction
+ if (distance > 0) {
+ factor = -coefficient * ewc * Math.log(1 + distance) /
+ distance /
+ NodeMatrix[np(n1, 'mass')];
+ }
+ }
+ else {
+
+ //-- LinLog Anti-collision Attraction
+ if (distance > 0) {
+ factor = -coefficient * ewc * Math.log(1 + distance) / distance;
+ }
+ }
+ }
+ else {
+ if (W.settings.outboundAttractionDistribution) {
+
+ //-- Linear Degree Distributed Anti-collision Attraction
+ if (distance > 0) {
+ factor = -coefficient * ewc / NodeMatrix[np(n1, 'mass')];
+ }
+ }
+ else {
+
+ //-- Linear Anti-collision Attraction
+ if (distance > 0) {
+ factor = -coefficient * ewc;
+ }
+ }
+ }
+ }
+ else {
+
+ distance = Math.sqrt(
+ Math.pow(xDist, 2) + Math.pow(yDist, 2)
+ );
+
+ if (W.settings.linLogMode) {
+ if (W.settings.outboundAttractionDistribution) {
+
+ //-- LinLog Degree Distributed Attraction
+ if (distance > 0) {
+ factor = -coefficient * ewc * Math.log(1 + distance) /
+ distance /
+ NodeMatrix[np(n1, 'mass')];
+ }
+ }
+ else {
+
+ //-- LinLog Attraction
+ if (distance > 0)
+ factor = -coefficient * ewc * Math.log(1 + distance) / distance;
+ }
+ }
+ else {
+ if (W.settings.outboundAttractionDistribution) {
+
+ //-- Linear Attraction Mass Distributed
+ // NOTE: Distance is set to 1 to override next condition
+ distance = 1;
+ factor = -coefficient * ewc / NodeMatrix[np(n1, 'mass')];
+ }
+ else {
+
+ //-- Linear Attraction
+ // NOTE: Distance is set to 1 to override next condition
+ distance = 1;
+ factor = -coefficient * ewc;
+ }
+ }
+ }
+
+ // Updating nodes' dx and dy
+ // TODO: if condition or factor = 1?
+ if (distance > 0) {
+
+ // Updating nodes' dx and dy
+ NodeMatrix[np(n1, 'dx')] += xDist * factor;
+ NodeMatrix[np(n1, 'dy')] += yDist * factor;
+
+ NodeMatrix[np(n2, 'dx')] -= xDist * factor;
+ NodeMatrix[np(n2, 'dy')] -= yDist * factor;
+ }
+ }
+
+
+ // 5) Apply Forces
+ //-----------------
+ var force,
+ swinging,
+ traction,
+ nodespeed;
+
+ // MATH: sqrt and square distances
+ if (W.settings.adjustSizes) {
+
+ for (n = 0; n < W.nodesLength; n += W.ppn) {
+ if (!NodeMatrix[np(n, 'fixed')]) {
+ force = Math.sqrt(
+ Math.pow(NodeMatrix[np(n, 'dx')], 2) +
+ Math.pow(NodeMatrix[np(n, 'dy')], 2)
+ );
+
+ if (force > W.maxForce) {
+ NodeMatrix[np(n, 'dx')] =
+ NodeMatrix[np(n, 'dx')] * W.maxForce / force;
+ NodeMatrix[np(n, 'dy')] =
+ NodeMatrix[np(n, 'dy')] * W.maxForce / force;
+ }
+
+ swinging = NodeMatrix[np(n, 'mass')] *
+ Math.sqrt(
+ (NodeMatrix[np(n, 'old_dx')] - NodeMatrix[np(n, 'dx')]) *
+ (NodeMatrix[np(n, 'old_dx')] - NodeMatrix[np(n, 'dx')]) +
+ (NodeMatrix[np(n, 'old_dy')] - NodeMatrix[np(n, 'dy')]) *
+ (NodeMatrix[np(n, 'old_dy')] - NodeMatrix[np(n, 'dy')])
+ );
+
+ traction = Math.sqrt(
+ (NodeMatrix[np(n, 'old_dx')] + NodeMatrix[np(n, 'dx')]) *
+ (NodeMatrix[np(n, 'old_dx')] + NodeMatrix[np(n, 'dx')]) +
+ (NodeMatrix[np(n, 'old_dy')] + NodeMatrix[np(n, 'dy')]) *
+ (NodeMatrix[np(n, 'old_dy')] + NodeMatrix[np(n, 'dy')])
+ ) / 2;
+
+ nodespeed =
+ 0.1 * Math.log(1 + traction) / (1 + Math.sqrt(swinging));
+
+ // Updating node's positon
+ NodeMatrix[np(n, 'x')] =
+ NodeMatrix[np(n, 'x')] + NodeMatrix[np(n, 'dx')] *
+ (nodespeed / W.settings.slowDown);
+ NodeMatrix[np(n, 'y')] =
+ NodeMatrix[np(n, 'y')] + NodeMatrix[np(n, 'dy')] *
+ (nodespeed / W.settings.slowDown);
+ }
+ }
+ }
+ else {
+
+ for (n = 0; n < W.nodesLength; n += W.ppn) {
+ if (!NodeMatrix[np(n, 'fixed')]) {
+
+ swinging = NodeMatrix[np(n, 'mass')] *
+ Math.sqrt(
+ (NodeMatrix[np(n, 'old_dx')] - NodeMatrix[np(n, 'dx')]) *
+ (NodeMatrix[np(n, 'old_dx')] - NodeMatrix[np(n, 'dx')]) +
+ (NodeMatrix[np(n, 'old_dy')] - NodeMatrix[np(n, 'dy')]) *
+ (NodeMatrix[np(n, 'old_dy')] - NodeMatrix[np(n, 'dy')])
+ );
+
+ traction = Math.sqrt(
+ (NodeMatrix[np(n, 'old_dx')] + NodeMatrix[np(n, 'dx')]) *
+ (NodeMatrix[np(n, 'old_dx')] + NodeMatrix[np(n, 'dx')]) +
+ (NodeMatrix[np(n, 'old_dy')] + NodeMatrix[np(n, 'dy')]) *
+ (NodeMatrix[np(n, 'old_dy')] + NodeMatrix[np(n, 'dy')])
+ ) / 2;
+
+ nodespeed = NodeMatrix[np(n, 'convergence')] *
+ Math.log(1 + traction) / (1 + Math.sqrt(swinging));
+
+ // Updating node convergence
+ NodeMatrix[np(n, 'convergence')] =
+ Math.min(1, Math.sqrt(
+ nodespeed *
+ (Math.pow(NodeMatrix[np(n, 'dx')], 2) +
+ Math.pow(NodeMatrix[np(n, 'dy')], 2)) /
+ (1 + Math.sqrt(swinging))
+ ));
+
+ // Updating node's positon
+ NodeMatrix[np(n, 'x')] =
+ NodeMatrix[np(n, 'x')] + NodeMatrix[np(n, 'dx')] *
+ (nodespeed / W.settings.slowDown);
+ NodeMatrix[np(n, 'y')] =
+ NodeMatrix[np(n, 'y')] + NodeMatrix[np(n, 'dy')] *
+ (nodespeed / W.settings.slowDown);
+ }
+ }
+ }
+
+ // Counting one more iteration
+ W.iterations++;
+ }
+
+ /**
+ * Message reception & sending
+ */
+
+ // Sending data back to the supervisor
+ var sendNewCoords;
+
+ if (typeof window !== 'undefined' && window.document) {
+
+ // From same document as sigma
+ sendNewCoords = function() {
+ var e;
+
+ if (document.createEvent) {
+ e = document.createEvent('Event');
+ e.initEvent('newCoords', true, false);
+ }
+ else {
+ e = document.createEventObject();
+ e.eventType = 'newCoords';
+ }
+
+ e.eventName = 'newCoords';
+ e.data = {
+ nodes: NodeMatrix.buffer
+ };
+ requestAnimationFrame(function() {
+ document.dispatchEvent(e);
+ });
+ };
+ }
+ else {
+
+ // From a WebWorker
+ sendNewCoords = function() {
+ self.postMessage(
+ {nodes: NodeMatrix.buffer},
+ [NodeMatrix.buffer]
+ );
+ };
+ }
+
+ // Algorithm run
+ function run(n) {
+ for (var i = 0; i < n; i++)
+ pass();
+ sendNewCoords();
+ }
+
+ // On supervisor message
+ var listener = function(e) {
+ switch (e.data.action) {
+ case 'start':
+ init(
+ new Float32Array(e.data.nodes),
+ new Float32Array(e.data.edges),
+ e.data.config
+ );
+
+ // First iteration(s)
+ run(W.settings.startingIterations);
+ break;
+
+ case 'loop':
+ NodeMatrix = new Float32Array(e.data.nodes);
+ run(W.settings.iterationsPerRender);
+ break;
+
+ case 'config':
+
+ // Merging new settings
+ configure(e.data.config);
+ break;
+
+ case 'kill':
+
+ // Deleting context for garbage collection
+ __emptyObject(W);
+ NodeMatrix = null;
+ EdgeMatrix = null;
+ RegionMatrix = null;
+ self.removeEventListener('message', listener);
+ break;
+
+ default:
+ }
+ };
+
+ // Adding event listener
+ self.addEventListener('message', listener);
+ };
+
+
+ /**
+ * Exporting
+ * ----------
+ *
+ * Crush the worker function and make it accessible by sigma's instances so
+ * the supervisor can call it.
+ */
+ function crush(fnString) {
+ var pattern,
+ i,
+ l;
+
+ var np = [
+ 'x',
+ 'y',
+ 'dx',
+ 'dy',
+ 'old_dx',
+ 'old_dy',
+ 'mass',
+ 'convergence',
+ 'size',
+ 'fixed'
+ ];
+
+ var ep = [
+ 'source',
+ 'target',
+ 'weight'
+ ];
+
+ var rp = [
+ 'node',
+ 'centerX',
+ 'centerY',
+ 'size',
+ 'nextSibling',
+ 'firstChild',
+ 'mass',
+ 'massCenterX',
+ 'massCenterY'
+ ];
+
+ // rp
+ // NOTE: Must go first
+ for (i = 0, l = rp.length; i < l; i++) {
+ pattern = new RegExp('rp\\(([^,]*), \'' + rp[i] + '\'\\)', 'g');
+ fnString = fnString.replace(
+ pattern,
+ (i === 0) ? '$1' : '$1 + ' + i
+ );
+ }
+
+ // np
+ for (i = 0, l = np.length; i < l; i++) {
+ pattern = new RegExp('np\\(([^,]*), \'' + np[i] + '\'\\)', 'g');
+ fnString = fnString.replace(
+ pattern,
+ (i === 0) ? '$1' : '$1 + ' + i
+ );
+ }
+
+ // ep
+ for (i = 0, l = ep.length; i < l; i++) {
+ pattern = new RegExp('ep\\(([^,]*), \'' + ep[i] + '\'\\)', 'g');
+ fnString = fnString.replace(
+ pattern,
+ (i === 0) ? '$1' : '$1 + ' + i
+ );
+ }
+
+ return fnString;
+ }
+
+ // Exporting
+ function getWorkerFn() {
+ var fnString = crush ? crush(Worker.toString()) : Worker.toString();
+ return ';(' + fnString + ').call(this);';
+ }
+
+ if (inWebWorker) {
+
+ // We are in a webworker, so we launch the Worker function
+ eval(getWorkerFn());
+ }
+ else {
+
+ // We are requesting the worker from sigma, we retrieve it therefore
+ if (typeof sigma === 'undefined')
+ throw 'sigma is not declared';
+
+ sigma.prototype.getForceAtlas2Worker = getWorkerFn;
+ }
+}).call(this);
diff --git a/blogContent/projects/steam/src/plugins/sigma.layout.noverlap/README.md b/blogContent/projects/steam/src/plugins/sigma.layout.noverlap/README.md
new file mode 100644
index 0000000..7b954aa
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.layout.noverlap/README.md
@@ -0,0 +1,87 @@
+sigma.layout.noverlap
+========================
+
+Plugin developed by [Andrew Pitts](https://github.com/apitts) and published under the [MIT](LICENSE) license. Original algorithm by [Mathieu Jacomy](https://github.com/jacomyma) and ported to sigma.js with permission.
+
+---
+
+This plugin runs an algorithm which distributes nodes in the network, ensuring that they do not overlap and providing a margin where specified.
+
+## Methods
+
+**configure**
+
+Changes the layout's configuration.
+
+```js
+var listener = s.configNoverlap(config);
+```
+
+**start**
+
+Starts the layout. It is possible to pass a configuration if this is the first time you start the layout.
+
+```js
+s.startNoverlap();
+```
+
+**isRunning**
+
+Returns whether the layout is running.
+
+```js
+s.isNoverlapRunning();
+```
+
+## Configuration
+
+* **nodes**: *array*: the subset of nodes to apply the layout.
+
+*Algorithm configuration*
+
+* **nodeMargin**: *number* `5.0`: The additional minimum space to apply around each and every node.
+* **scaleNodes**: *number* `1.2`: A multiplier to apply to nodes such that larger nodes will have more space around them if this multiplier is greater than zero.
+* **gridSize**: *integer* `20`: The number of rows and columns to use when dividing the nodes up into cells which the algorithm is applied to. Use more rows and columns for larger graphs for a more efficient algorithm.
+* **permittedExpansion** *number* `1.1`: At every step, this is the maximum ratio to apply to the bounding box, i.e. the maximum by which the network is permitted to expand.
+* **rendererIndex** *integer* `0`: The index of the renderer to use to compute overlap and collisions of the nodes.
+* **speed** *number* `2`: A larger value increases the speed with which the algorithm will convergence at the cost of precision.
+* **maxIterations** *number* `500`: The maximum number of iterations to run the algorithm for before stopping it.
+
+*Easing configuration*
+
+* **easing** *string*: if specified, ease the transition between nodes positions if background is `true`. The duration is specified by the Sigma settings `animationsTime`. See [sigma.utils.easing](../../src/utils/sigma.utils.js#L723) for available values.
+* **duration** *number*: duration of the transition for the easing method. Default value is Sigma setting `animationsTime`.
+
+## Events
+
+The plugin dispatches the following events:
+
+- `start`: on layout start.
+- `interpolate`: at the beginning of the layout animation if an *easing* function is specified and the layout is ran on background.
+- `stop`: on layout stop, will be dispatched after `interpolate`.
+
+Example:
+
+```js
+
+s = new sigma({
+ graph: g,
+ container: 'graph-container'
+});
+
+var config = {
+ nodeMargin: 3.0,
+ scaleNodes: 1.3
+};
+
+// Configure the algorithm
+var listener = s.configNoverlap(config);
+
+// Bind all events:
+listener.bind('start stop interpolate', function(event) {
+ console.log(event.type);
+});
+
+// Start the algorithm:
+s.startNoverlap();
+```
\ No newline at end of file
diff --git a/blogContent/projects/steam/src/plugins/sigma.layout.noverlap/sigma.layout.noverlap.js b/blogContent/projects/steam/src/plugins/sigma.layout.noverlap/sigma.layout.noverlap.js
new file mode 100644
index 0000000..6d4b3a4
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.layout.noverlap/sigma.layout.noverlap.js
@@ -0,0 +1,408 @@
+;(function(undefined) {
+ 'use strict';
+
+ if (typeof sigma === 'undefined')
+ throw new Error('sigma is not declared');
+
+ // Initialize package:
+ sigma.utils.pkg('sigma.layout.noverlap');
+
+ /**
+ * Noverlap Layout
+ * ===============================
+ *
+ * Author: @apitts / Andrew Pitts
+ * Algorithm: @jacomyma / Mathieu Jacomy (originally contributed to Gephi and ported to sigma.js under the MIT license by @andpitts with permission)
+ * Acknowledgement: @sheyman / Sébastien Heymann (some inspiration has been taken from other MIT licensed layout algorithms authored by @sheyman)
+ * Version: 0.1
+ */
+
+ var settings = {
+ speed: 3,
+ scaleNodes: 1.2,
+ nodeMargin: 5.0,
+ gridSize: 20,
+ permittedExpansion: 1.1,
+ rendererIndex: 0,
+ maxIterations: 500
+ };
+
+ var _instance = {};
+
+ /**
+ * Event emitter Object
+ * ------------------
+ */
+ var _eventEmitter = {};
+
+ /**
+ * Noverlap Object
+ * ------------------
+ */
+ function Noverlap() {
+ var self = this;
+
+ this.init = function (sigInst, options) {
+ options = options || {};
+
+ // Properties
+ this.sigInst = sigInst;
+ this.config = sigma.utils.extend(options, settings);
+ this.easing = options.easing;
+ this.duration = options.duration;
+
+ if (options.nodes) {
+ this.nodes = options.nodes;
+ delete options.nodes;
+ }
+
+ if (!sigma.plugins || typeof sigma.plugins.animate === 'undefined') {
+ throw new Error('sigma.plugins.animate is not declared');
+ }
+
+ // State
+ this.running = false;
+ };
+
+ /**
+ * Single layout iteration.
+ */
+ this.atomicGo = function () {
+ if (!this.running || this.iterCount < 1) return false;
+
+ var nodes = this.nodes || this.sigInst.graph.nodes(),
+ nodesCount = nodes.length,
+ i,
+ n,
+ n1,
+ n2,
+ xmin = Infinity,
+ xmax = -Infinity,
+ ymin = Infinity,
+ ymax = -Infinity,
+ xwidth,
+ yheight,
+ xcenter,
+ ycenter,
+ grid,
+ row,
+ col,
+ minXBox,
+ maxXBox,
+ minYBox,
+ maxYBox,
+ adjacentNodes,
+ subRow,
+ subCol,
+ nxmin,
+ nxmax,
+ nymin,
+ nymax;
+
+ this.iterCount--;
+ this.running = false;
+
+ for (i=0; i < nodesCount; i++) {
+ n = nodes[i];
+ n.dn.dx = 0;
+ n.dn.dy = 0;
+
+ //Find the min and max for both x and y across all nodes
+ xmin = Math.min(xmin, n.dn_x - (n.dn_size*self.config.scaleNodes + self.config.nodeMargin) );
+ xmax = Math.max(xmax, n.dn_x + (n.dn_size*self.config.scaleNodes + self.config.nodeMargin) );
+ ymin = Math.min(ymin, n.dn_y - (n.dn_size*self.config.scaleNodes + self.config.nodeMargin) );
+ ymax = Math.max(ymax, n.dn_y + (n.dn_size*self.config.scaleNodes + self.config.nodeMargin) );
+
+ }
+
+ xwidth = xmax - xmin;
+ yheight = ymax - ymin;
+ xcenter = (xmin + xmax) / 2;
+ ycenter = (ymin + ymax) / 2;
+ xmin = xcenter - self.config.permittedExpansion*xwidth / 2;
+ xmax = xcenter + self.config.permittedExpansion*xwidth / 2;
+ ymin = ycenter - self.config.permittedExpansion*yheight / 2;
+ ymax = ycenter + self.config.permittedExpansion*yheight / 2;
+
+ grid = {}; //An object of objects where grid[row][col] is an array of node ids representing nodes that fall in that grid. Nodes can fall in more than one grid
+
+ for(row = 0; row < self.config.gridSize; row++) {
+ grid[row] = {};
+ for(col = 0; col < self.config.gridSize; col++) {
+ grid[row][col] = [];
+ }
+ }
+
+ //Place nodes in grid
+ for (i=0; i < nodesCount; i++) {
+ n = nodes[i];
+
+ nxmin = n.dn_x - (n.dn_size*self.config.scaleNodes + self.config.nodeMargin);
+ nxmax = n.dn_x + (n.dn_size*self.config.scaleNodes + self.config.nodeMargin);
+ nymin = n.dn_y - (n.dn_size*self.config.scaleNodes + self.config.nodeMargin);
+ nymax = n.dn_y + (n.dn_size*self.config.scaleNodes + self.config.nodeMargin);
+
+ minXBox = Math.floor(self.config.gridSize* (nxmin - xmin) / (xmax - xmin) );
+ maxXBox = Math.floor(self.config.gridSize* (nxmax - xmin) / (xmax - xmin) );
+ minYBox = Math.floor(self.config.gridSize* (nymin - ymin) / (ymax - ymin) );
+ maxYBox = Math.floor(self.config.gridSize* (nymax - ymin) / (ymax - ymin) );
+ for(col = minXBox; col <= maxXBox; col++) {
+ for(row = minYBox; row <= maxYBox; row++) {
+ grid[row][col].push(n.id);
+ }
+ }
+ }
+
+
+ adjacentNodes = {}; //An object that stores the node ids of adjacent nodes (either in same grid box or adjacent grid box) for all nodes
+
+ for(row = 0; row < self.config.gridSize; row++) {
+ for(col = 0; col < self.config.gridSize; col++) {
+ grid[row][col].forEach(function(nodeId) {
+ if(!adjacentNodes[nodeId]) {
+ adjacentNodes[nodeId] = [];
+ }
+ for(subRow = Math.max(0, row - 1); subRow <= Math.min(row + 1, self.config.gridSize - 1); subRow++) {
+ for(subCol = Math.max(0, col - 1); subCol <= Math.min(col + 1, self.config.gridSize - 1); subCol++) {
+ grid[subRow][subCol].forEach(function(subNodeId) {
+ if(subNodeId !== nodeId && adjacentNodes[nodeId].indexOf(subNodeId) === -1) {
+ adjacentNodes[nodeId].push(subNodeId);
+ }
+ });
+ }
+ }
+ });
+ }
+ }
+
+ //If two nodes overlap then repulse them
+ for (i=0; i < nodesCount; i++) {
+ n1 = nodes[i];
+ adjacentNodes[n1.id].forEach(function(nodeId) {
+ var n2 = self.sigInst.graph.nodes(nodeId);
+ var xDist = n2.dn_x - n1.dn_x;
+ var yDist = n2.dn_y - n1.dn_y;
+ var dist = Math.sqrt(xDist*xDist + yDist*yDist);
+ var collision = (dist < ((n1.dn_size*self.config.scaleNodes + self.config.nodeMargin) + (n2.dn_size*self.config.scaleNodes + self.config.nodeMargin)));
+ if(collision) {
+ self.running = true;
+ if(dist > 0) {
+ n2.dn.dx += xDist / dist * (1 + n1.dn_size);
+ n2.dn.dy += yDist / dist * (1 + n1.dn_size);
+ } else {
+ n2.dn.dx += xwidth * 0.01 * (0.5 - Math.random());
+ n2.dn.dy += yheight * 0.01 * (0.5 - Math.random());
+ }
+ }
+ });
+ }
+
+ for (i=0; i < nodesCount; i++) {
+ n = nodes[i];
+ if(!n.fixed) {
+ n.dn_x = n.dn_x + n.dn.dx * 0.1 * self.config.speed;
+ n.dn_y = n.dn_y + n.dn.dy * 0.1 * self.config.speed;
+ }
+ }
+
+ if(this.running && this.iterCount < 1) {
+ this.running = false;
+ }
+
+ return this.running;
+ };
+
+ this.go = function () {
+ this.iterCount = this.config.maxIterations;
+
+ while (this.running) {
+ this.atomicGo();
+ };
+
+ this.stop();
+ };
+
+ this.start = function() {
+ if (this.running) return;
+
+ var nodes = this.sigInst.graph.nodes();
+
+ var prefix = this.sigInst.renderers[self.config.rendererIndex].options.prefix;
+
+ this.running = true;
+
+ // Init nodes
+ for (var i = 0; i < nodes.length; i++) {
+ nodes[i].dn_x = nodes[i][prefix + 'x'];
+ nodes[i].dn_y = nodes[i][prefix + 'y'];
+ nodes[i].dn_size = nodes[i][prefix + 'size'];
+ nodes[i].dn = {
+ dx: 0,
+ dy: 0
+ };
+ }
+ _eventEmitter[self.sigInst.id].dispatchEvent('start');
+ this.go();
+ };
+
+ this.stop = function() {
+ var nodes = this.sigInst.graph.nodes();
+
+ this.running = false;
+
+ if (this.easing) {
+ _eventEmitter[self.sigInst.id].dispatchEvent('interpolate');
+ sigma.plugins.animate(
+ self.sigInst,
+ {
+ x: 'dn_x',
+ y: 'dn_y'
+ },
+ {
+ easing: self.easing,
+ onComplete: function() {
+ self.sigInst.refresh();
+ for (var i = 0; i < nodes.length; i++) {
+ nodes[i].dn = null;
+ nodes[i].dn_x = null;
+ nodes[i].dn_y = null;
+ }
+ _eventEmitter[self.sigInst.id].dispatchEvent('stop');
+ },
+ duration: self.duration
+ }
+ );
+ }
+ else {
+ // Apply changes
+ for (var i = 0; i < nodes.length; i++) {
+ nodes[i].x = nodes[i].dn_x;
+ nodes[i].y = nodes[i].dn_y;
+ }
+
+ this.sigInst.refresh();
+
+ for (var i = 0; i < nodes.length; i++) {
+ nodes[i].dn = null;
+ nodes[i].dn_x = null;
+ nodes[i].dn_y = null;
+ }
+ _eventEmitter[self.sigInst.id].dispatchEvent('stop');
+ }
+ };
+
+ this.kill = function() {
+ this.sigInst = null;
+ this.config = null;
+ this.easing = null;
+ };
+ };
+
+ /**
+ * Interface
+ * ----------
+ */
+
+ /**
+ * Configure the layout algorithm.
+
+ * Recognized options:
+ * **********************
+ * Here is the exhaustive list of every accepted parameter in the settings
+ * object:
+ *
+ * {?number} speed A larger value increases the convergence speed at the cost of precision
+ * {?number} scaleNodes The ratio to scale nodes by - a larger ratio will lead to more space around larger nodes
+ * {?number} nodeMargin A fixed margin to apply around nodes regardless of size
+ * {?number} maxIterations The maximum number of iterations to perform before the layout completes.
+ * {?integer} gridSize The number of rows and columns to use when partioning nodes into a grid for efficient computation
+ * {?number} permittedExpansion A permitted expansion factor to the overall size of the network applied at each iteration
+ * {?integer} rendererIndex The index of the renderer to use for node co-ordinates. Defaults to zero.
+ * {?(function|string)} easing Either the name of an easing in the sigma.utils.easings package or a function. If not specified, the
+ * quadraticInOut easing from this package will be used instead.
+ * {?number} duration The duration of the animation. If not specified, the "animationsTime" setting value of the sigma instance will be used instead.
+ *
+ *
+ * @param {object} config The optional configuration object.
+ *
+ * @return {sigma.classes.dispatcher} Returns an event emitter.
+ */
+ sigma.prototype.configNoverlap = function(config) {
+
+ var sigInst = this;
+
+ if (!config) throw new Error('Missing argument: "config"');
+
+ // Create instance if undefined
+ if (!_instance[sigInst.id]) {
+ _instance[sigInst.id] = new Noverlap();
+
+ _eventEmitter[sigInst.id] = {};
+ sigma.classes.dispatcher.extend(_eventEmitter[sigInst.id]);
+
+ // Binding on kill to clear the references
+ sigInst.bind('kill', function() {
+ _instance[sigInst.id].kill();
+ _instance[sigInst.id] = null;
+ _eventEmitter[sigInst.id] = null;
+ });
+ }
+
+ _instance[sigInst.id].init(sigInst, config);
+
+ return _eventEmitter[sigInst.id];
+ };
+
+ /**
+ * Start the layout algorithm. It will use the existing configuration if no
+ * new configuration is passed.
+
+ * Recognized options:
+ * **********************
+ * Here is the exhaustive list of every accepted parameter in the settings
+ * object
+ *
+ * {?number} speed A larger value increases the convergence speed at the cost of precision
+ * {?number} scaleNodes The ratio to scale nodes by - a larger ratio will lead to more space around larger nodes
+ * {?number} nodeMargin A fixed margin to apply around nodes regardless of size
+ * {?number} maxIterations The maximum number of iterations to perform before the layout completes.
+ * {?integer} gridSize The number of rows and columns to use when partioning nodes into a grid for efficient computation
+ * {?number} permittedExpansion A permitted expansion factor to the overall size of the network applied at each iteration
+ * {?integer} rendererIndex The index of the renderer to use for node co-ordinates. Defaults to zero.
+ * {?(function|string)} easing Either the name of an easing in the sigma.utils.easings package or a function. If not specified, the
+ * quadraticInOut easing from this package will be used instead.
+ * {?number} duration The duration of the animation. If not specified, the "animationsTime" setting value of the sigma instance will be used instead.
+ *
+ *
+ *
+ * @param {object} config The optional configuration object.
+ *
+ * @return {sigma.classes.dispatcher} Returns an event emitter.
+ */
+
+ sigma.prototype.startNoverlap = function(config) {
+
+ var sigInst = this;
+
+ if (config) {
+ this.configNoverlap(sigInst, config);
+ }
+
+ _instance[sigInst.id].start();
+
+ return _eventEmitter[sigInst.id];
+ };
+
+ /**
+ * Returns true if the layout has started and is not completed.
+ *
+ * @return {boolean}
+ */
+ sigma.prototype.isNoverlapRunning = function() {
+
+ var sigInst = this;
+
+ return !!_instance[sigInst.id] && _instance[sigInst.id].running;
+ };
+
+}).call(this);
\ No newline at end of file
diff --git a/blogContent/projects/steam/src/plugins/sigma.neo4j.cypher/LICENSE b/blogContent/projects/steam/src/plugins/sigma.neo4j.cypher/LICENSE
new file mode 100644
index 0000000..c9f3b20
--- /dev/null
+++ b/blogContent/projects/steam/src/plugins/sigma.neo4j.cypher/LICENSE
@@ -0,0 +1,553 @@
+GNU GENERAL PUBLIC LICENSE
+Version 3, 29 June 2007
+Copyright (C) 2007 Free Software Foundation, Inc.