├── .gitignore ├── img ├── hodd.png ├── icon.png ├── icon.xcf ├── icon-192.png └── hodd-mobile.png ├── fonts └── ionicons.woff2 ├── css ├── style.css ├── ionicons.min.css └── bootstrap-vue.min.css ├── hodd.webmanifest ├── LICENSE.md ├── README.md ├── js ├── vue-clipboard.min.js ├── app.js ├── app_slim.js ├── popper.min.js └── paho-mqtt.js ├── index_slim.html └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | settings.js 2 | js/vue.js 3 | mock_data.js 4 | -------------------------------------------------------------------------------- /img/hodd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rroemhild/hodd/HEAD/img/hodd.png -------------------------------------------------------------------------------- /img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rroemhild/hodd/HEAD/img/icon.png -------------------------------------------------------------------------------- /img/icon.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rroemhild/hodd/HEAD/img/icon.xcf -------------------------------------------------------------------------------- /img/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rroemhild/hodd/HEAD/img/icon-192.png -------------------------------------------------------------------------------- /img/hodd-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rroemhild/hodd/HEAD/img/hodd-mobile.png -------------------------------------------------------------------------------- /fonts/ionicons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rroemhild/hodd/HEAD/fonts/ionicons.woff2 -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | min-height: 75rem; 3 | padding-top: 4.5rem; 4 | } 5 | 6 | .bd-placeholder-img { 7 | font-size: 1.125rem; 8 | text-anchor: middle; 9 | -webkit-user-select: none; 10 | -moz-user-select: none; 11 | -ms-user-select: none; 12 | user-select: none; 13 | } 14 | 15 | @media (min-width: 768px) { 16 | .bd-placeholder-img-lg { 17 | font-size: 3.5rem; 18 | } 19 | } 20 | 21 | .card-col { 22 | padding-bottom: 10px; 23 | } 24 | -------------------------------------------------------------------------------- /hodd.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Homie Device Discovery", 3 | "short_name": "HoDD", 4 | "description": "Shows Homie devices on a MQTT server.", 5 | "icons": [ 6 | { 7 | "src": "img/icon.png", 8 | "type": "image/png", 9 | "sizes": "512x512" 10 | }, 11 | { 12 | "src": "img/icon-192.png", 13 | "type": "image/png", 14 | "sizes": "192x192" 15 | } 16 | ], 17 | "screenshots": [ 18 | { 19 | "src": "img/hodd.png", 20 | "type": "image/png", 21 | "sizes": "1276x709", 22 | "form_factor": "wide" 23 | }, 24 | { 25 | "src": "img/hodd-mobile.png", 26 | "type": "image/png", 27 | "sizes": "1080x2400", 28 | "form_factor": "narrow" 29 | } 30 | ], 31 | "background_color": "#ffffff", 32 | "start_url": ".", 33 | "id": "/hodd", 34 | "display": "standalone", 35 | "categories": ["networking", "utilities"], 36 | "lang": "en" 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © 2019-2020 Rafael Römhild 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HoDD - Homie Device Discovery 2 | 3 | HoDD is a simple client-side (Browser) app to discover [Homie](https://homieiot.github.io) devices. It's a little helper for developing Homie devices or just to spot the amount of Homie devices you are running at home. 4 | 5 | Try it online: https://rroemhild.github.io/hodd/ 6 | 7 | ### What's included 8 | 9 | * Runs complete in your browser, no server side setup 10 | * Auto discover devices and display them in cards with all attributes, nodes and properties 11 | * Interact with settable properties, no data validation and only rgb support for color 12 | * Clickable clipboard icon to copy topics to clipboard 13 | * Support for Homie 4.0 and 3.0.1 (without arrays) 14 | * Extensions (Homie 4.0) 15 | * Legacy Firmware (org.homie.legacy-firmware:0.1.1:[4.x]) 16 | * Legacy Stats (org.homie.legacy-stats:0.1.1:[4.x]) 17 | * Microhomie MPy (org.microhomie.mpy:0.1.0:[4.x]) 18 | 19 | 20 | ### Installation 21 | 22 | * Clone this repository or download the latest release archive 23 | * Open the `index.html` file in your browser 24 | * Make your settings and connect 25 | 26 | 27 | ### Requierements 28 | 29 | * MQTT broker with WebSockets, like the [Mosquitto](https://mosquitto.org/) broker. 30 | 31 | If you use the Mosquitto test broker, change the port to 8081 SSL enabled. 32 | 33 | 34 | ### Screenshot with example data 35 | 36 | ![HoDD Screenshot](img/hodd.png) 37 | -------------------------------------------------------------------------------- /js/vue-clipboard.min.js: -------------------------------------------------------------------------------- 1 | (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 2 | 3 | 4 | 5 | 9 | 10 | 11 | Homie Device Discovery 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | Homie Device Discovery 23 | 24 | Settings 29 | 30 | 31 | 41 | 42 | 47 | 52 | 53 | 54 | 60 | 65 | 72 | SSL 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 86 | 87 | 88 | 93 | 98 | 99 | 100 | 101 | 102 | 103 |
104 | 105 | 106 |
107 | 108 | 109 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | Device ID: 121 | {{ device.id }} 122 | 123 | 124 | Homie Version: 125 | {{ device.homie }} 126 | 127 | 128 | Implementation: 129 | 130 | {{ device.implementation }} 131 | 132 | 133 | 134 | 135 | 136 | 140 |
141 | 142 | Reset 143 | WebREPL 144 | Yaota8266 145 | 146 |
147 |
148 | 149 | 153 | 154 | 155 | Firmware Name: 156 | {{ device.fw_name }} 157 | 158 | 159 | Firmware Version: 160 | {{ device.fw_version }} 161 | 162 | 163 | IP Address: 164 | {{ device.localip }} 165 | 166 | 167 | MAC Address: 168 | {{ device.mac }} 169 | 170 | 171 | 172 | 173 | 177 | 178 | 179 | Uptime: 180 | 181 | {{ timeSince(device.stats_uptime) }} 182 | 183 | 184 | 185 | Free heap: 186 | 187 | {{ device.stats_freeheap }} 188 | 189 | 190 | 191 | Stats interval: 192 | 193 | {{ device.stats_interval }} seconds 194 | 195 | 196 | 197 | 198 | 199 | 200 | 205 |
{{ node.name }}
206 | 210 | 211 | 217 | {{ property.name }}: 218 | 219 | 220 | 221 | 222 | 225 | 236 | {{ property.unit }} 237 | 238 | 239 | 240 | 243 | 247 | {{ property.unit }} 248 | 249 | 250 | 251 | 254 | 261 | {{ property.unit }} 262 | 263 | 264 | 265 | 266 | 271 | {{ property.unit }} 272 | 273 | 274 | 275 | 280 | {{ property.state }} 281 | {{ property.unit }} 282 | 283 | 284 | 285 |
286 |
287 |
288 |
289 | 290 | 291 | 294 | 295 | 301 | 302 | {{ device.name }} 303 | 304 |
305 | wipe 312 | 313 | {{ device.state }} 314 | 315 |
316 |
317 |
318 | 319 |
320 |
321 |
322 |
323 |
324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | Homie Device Discovery 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | Homie Device Discovery 26 | 27 | Settings 32 | 33 | 34 | 44 | 45 | 50 | 55 | 56 | 57 | 63 | 68 | 75 | SSL 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 89 | 90 | 91 | 96 | 101 | 102 | 103 | 104 | 105 | 106 |
107 | 108 |
109 | 110 | 111 | 116 | 117 | 118 | 119 | 125 | 126 | {{ device.name }} 127 | 128 |
129 | wipe 136 | 137 | {{ device.state }} 138 | 139 |
140 |
141 |
142 | 143 | 144 | 145 | 146 | 147 | Device ID: 148 | {{ device.id }} 149 | 150 | 151 | Homie Version: 152 | {{ device.homie }} 153 | 154 | 155 | Implementation: 156 | 157 | {{ device.implementation }} 158 | 159 | 160 | 161 | 162 | 163 | 167 |
168 | 169 | Reset 170 | WebREPL 171 | Yaota8266 172 | 173 |
174 |
175 | 176 | 180 | 181 | 182 | Firmware Name: 183 | {{ device.fw_name }} 184 | 185 | 186 | Firmware Version: 187 | {{ device.fw_version }} 188 | 189 | 190 | IP Address: 191 | {{ device.localip }} 192 | 193 | 194 | MAC Address: 195 | {{ device.mac }} 196 | 197 | 198 | 199 | 200 | 204 | 205 | 206 | Uptime: 207 | 208 | {{ timeSince(device.stats_uptime) }} 209 | 210 | 211 | 212 | Free heap: 213 | 214 | {{ device.stats_freeheap }} 215 | 216 | 217 | 218 | Signal: 219 | 220 | {{ device.stats_signal }} 221 | 222 | 223 | 224 | Stats interval: 225 | 226 | {{ device.stats_interval }} seconds 227 | 228 | 229 | 230 | 231 | 232 | 233 | 238 |
{{ node.name }}
239 | 243 | 244 | 250 | {{ property.name }}: 251 | 252 | 253 | 254 | 255 | 258 | 269 | {{ property.unit }} 270 | 271 | 272 | 273 | 276 | 280 | {{ property.unit }} 281 | 282 | 283 | 284 | 287 | 294 | {{ property.unit }} 295 | 296 | 297 | 298 | 299 | 304 | {{ property.unit }} 305 | 306 | 307 | 308 | 313 | {{ property.state }} 314 | {{ property.unit }} 315 | 316 | 317 | 318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * HoDD v0.4.0 3 | Homie Device Discovery 4 | * (c) 2019 Rafael Römhild 5 | * Released under the MIT License. 6 | */ 7 | 8 | var deviceTopics = {}; 9 | var deviceSubscriptions = {}; 10 | var colorPicker = VueColor.Compact; 11 | 12 | // MQTT client 13 | var BASE_TOPIC = "homie"; 14 | var DISCOVERY_TOPIC = `${BASE_TOPIC}/+/$homie`; 15 | var client = new Paho.Client("localhost", 8084, clientId()); 16 | 17 | // vue 18 | var devices = new Vue({ 19 | el: "#app", 20 | data: { 21 | deviceList: {} 22 | }, 23 | components: { "color-picker": colorPicker }, 24 | methods: { 25 | updateProperty: function(topic, event) { 26 | var set_topic = topic + "/set"; 27 | message = new Paho.Message(event); 28 | message.destinationName = set_topic; 29 | message.retained = false; 30 | message.qos = 1; 31 | client.send(message); 32 | }, 33 | badge_appearance: function(state) { 34 | if (state === "init") { 35 | return "info"; 36 | } else if (state === "ready") { 37 | return "success"; 38 | } else if (state === "lost") { 39 | return "warning"; 40 | } else if (state === "disconnected") { 41 | return "secondary"; 42 | } else if (state === "sleeping") { 43 | return "primary"; 44 | } else if (state === "alert") { 45 | return "danger"; 46 | } 47 | }, 48 | timeSince: function(secs) { 49 | var t = new Date(1970, 0, 1); 50 | t.setSeconds(secs); 51 | var s = t.toTimeString().substr(0, 8); 52 | if (secs > 86399) 53 | s = Math.floor((t - Date.parse("1/1/70")) / 3600000) + s.substr(2); 54 | return s; 55 | }, 56 | wipeDevice: function(deviceId) { 57 | // unsubscribe from topics 58 | for (var i = 0; i < deviceSubscriptions[deviceId].length; i++) { 59 | client.unsubscribe(deviceSubscriptions[deviceId][i]); 60 | } 61 | // remove all retained messages from topics 62 | for (var i = 0; i < deviceTopics[deviceId].length; i++) { 63 | message = new Paho.Message(""); 64 | message.destinationName = deviceTopics[deviceId][i]; 65 | message.retained = true; 66 | client.send(message); 67 | } 68 | 69 | // remove device from objects 70 | delete this.deviceList[deviceId]; 71 | delete deviceTopics[deviceId]; 72 | delete deviceSubscriptions[deviceId]; 73 | 74 | // update view 75 | this.$forceUpdate(); 76 | }, 77 | formatToArray: function(csv) { 78 | // comma seperated value 79 | var new_array = csv.split(","); 80 | return new_array; 81 | }, 82 | stringToRGB: function(v) { 83 | var rgb = v.split(","); 84 | return { r: parseInt(rgb[0]), g: parseInt(rgb[1]), b: parseInt(rgb[2]) }; 85 | }, 86 | updateRGBColor: function(t, v) { 87 | var colorString = v.rgba.r + "," + v.rgba.g + "," + v.rgba.b; 88 | var set_topic = t + "/set"; 89 | message = new Paho.Message(colorString); 90 | message.destinationName = set_topic; 91 | message.retained = false; 92 | client.send(message); 93 | }, 94 | doCopy: function(t, v) { 95 | this.$copyText(t); 96 | }, 97 | mpyCommand: function(t, v) { 98 | message = new Paho.Message(v); 99 | message.destinationName = t + "/$mpy"; 100 | message.retained = false; 101 | client.send(message); 102 | } 103 | } 104 | }); 105 | 106 | var client_status = new Vue({ 107 | el: "#client_status", 108 | data: { 109 | connected: false, 110 | message: "disconnected", 111 | broker: "localhost", 112 | port: 8084, 113 | ssl: "true", 114 | user: "", 115 | pass: "", 116 | reconnect: true, 117 | timeout: 10, 118 | clientId: clientId(), 119 | topic: BASE_TOPIC, 120 | autoConnect: "false" 121 | }, 122 | methods: { 123 | badge_appearance: function(state) { 124 | if (this.connected === true) { 125 | return "success"; 126 | } else { 127 | return "warning"; 128 | } 129 | }, 130 | settingsHandleOK(bvModalEvt) { 131 | BASE_TOPIC = this.topic; 132 | DISCOVERY_TOPIC = `${this.topic}/+/$homie`; 133 | connect_to_mqtt(this); 134 | } 135 | }, 136 | mounted() { 137 | if (localStorage.broker) { 138 | this.broker = localStorage.broker; 139 | } 140 | if (localStorage.user) { 141 | this.user = localStorage.user; 142 | } 143 | if (localStorage.pass) { 144 | this.pass = localStorage.pass; 145 | } 146 | if (localStorage.port) { 147 | this.port = localStorage.port; 148 | } 149 | if (localStorage.ssl) { 150 | this.ssl = localStorage.ssl; 151 | } 152 | if (localStorage.topic) { 153 | this.topic = localStorage.topic; 154 | } 155 | }, 156 | watch: { 157 | broker(newBroker) { 158 | localStorage.broker = newBroker; 159 | }, 160 | user(newUser) { 161 | localStorage.user = newUser; 162 | }, 163 | pass(newPass) { 164 | localStorage.pass = newPass; 165 | }, 166 | port(newPort) { 167 | localStorage.port = newPort; 168 | }, 169 | ssl(newSSL) { 170 | localStorage.ssl = newSSL; 171 | }, 172 | topic(newTopic) { 173 | localStorage.topic = newTopic; 174 | } 175 | } 176 | }); 177 | 178 | // Initiate the mqtt client and connect to mqtt 179 | function connect_to_mqtt(settings) { 180 | // disconnect before re-connect 181 | if (client.isConnected()) { 182 | console.log("Disconnect"); 183 | client.disconnect(); 184 | } 185 | 186 | console.log("Connecting..."); 187 | 188 | var options = { 189 | useSSL: settings.ssl === "true", 190 | onSuccess: onConnect, 191 | onFailure: doFail, 192 | reconnect: true, 193 | timeout: 10 194 | }; 195 | 196 | if (settings.user !== "") { 197 | options.userName = settings.user; 198 | if (settings.pass !== "") { 199 | options.password = settings.pass; 200 | } 201 | } 202 | 203 | // new client instance 204 | client = new Paho.Client( 205 | settings.broker, 206 | Number(settings.port), 207 | settings.clientId 208 | ); 209 | 210 | // set callback handlers 211 | client.onConnectionLost = onConnectionLost; 212 | client.onMessageArrived = onMessageArrived; 213 | 214 | client.connect(options); 215 | } 216 | 217 | // MQTT Client ID 218 | function clientId() { 219 | return ( 220 | "hodd_" + 221 | Math.random() 222 | .toString(16) 223 | .substr(2, 8) 224 | ); 225 | } 226 | 227 | function doFail(e) { 228 | console.log(e); 229 | client_status.connected = false; 230 | client_status.message = "disconnected"; 231 | } 232 | 233 | // called when the client connects 234 | function onConnect() { 235 | client_status.connected = true; 236 | client_status.message = "connected"; 237 | client.subscribe(DISCOVERY_TOPIC); 238 | } 239 | 240 | // called when the client looses its connection 241 | function onConnectionLost(responseObject) { 242 | if (responseObject.errorCode !== 0) { 243 | console.log("onConnectionLost:" + responseObject.errorMessage); 244 | } 245 | client_status.connected = false; 246 | client_status.message = "lost"; 247 | } 248 | 249 | // subscribe to topic and keep that info 250 | function subscribe(deviceId, topic) { 251 | client.subscribe(topic, 1); 252 | deviceSubscriptions[deviceId].push(topic); 253 | } 254 | 255 | // Unsubscribe from all topics to which we have previously subscribed which start with the given 256 | // prefix. 257 | function unsubscribePrefix(deviceId, topicPrefix) { 258 | var remainingSubscripions = []; 259 | for (topic of deviceSubscriptions[deviceId]) { 260 | if (topic.startsWith(topicPrefix)) { 261 | client.unsubscribe(topic); 262 | } else { 263 | remainingSubscripions.push(topic); 264 | } 265 | } 266 | deviceSubscriptions[deviceId] = remainingSubscripions; 267 | } 268 | 269 | // called when a message arrives 270 | function onMessageArrived(message) { 271 | // console.log("onMessageArrived: " + message.topic + " Payload: " + message.payloadString); 272 | 273 | // ignore /set topics 274 | if (message.destinationName.endsWith("/set")) { 275 | return; 276 | } 277 | 278 | var topic = message.destinationName.slice(BASE_TOPIC.length + 1).split("/"); 279 | var payload = message.payloadString; 280 | var device_id = topic[0]; 281 | 282 | // first message; add device to device list 283 | if (!(device_id in devices.deviceList)) { 284 | if (!payload) { 285 | return; 286 | } 287 | 288 | // add topic to deviceTopics 289 | deviceTopics[device_id] = [message.destinationName]; 290 | deviceSubscriptions[device_id] = []; 291 | 292 | devices.$set(devices.deviceList, device_id, { 293 | id: device_id, 294 | homie: payload, 295 | name: "", 296 | state: "", 297 | localip: "", 298 | mac: "", 299 | fw_name: "", 300 | fw_version: "", 301 | stats_interval: "", 302 | stats_uptime: "", 303 | stats_freeheap: "", 304 | stats_signal: "", 305 | implementation: "", 306 | nodes: {}, 307 | topic: `${BASE_TOPIC}/${topic[0]}`, 308 | extensions: [] 309 | }); 310 | 311 | // subscribe to device topics 312 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/+`); 313 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/$fw/+`); 314 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/$stats/+`); 315 | } else { 316 | // add topic to deviceTopics 317 | deviceTopics[device_id].push(message.destinationName); 318 | 319 | // process attributes and payloads 320 | if (topic[1] === "$name") { 321 | devices.deviceList[device_id]["name"] = payload; 322 | } else if (topic[1] === "$state") { 323 | devices.deviceList[device_id]["state"] = payload; 324 | } else if (topic[1] === "$localip") { 325 | devices.deviceList[device_id]["localip"] = payload; 326 | } else if (topic[1] === "$mac") { 327 | devices.deviceList[device_id]["mac"] = payload; 328 | } else if (topic[1] === "$implementation") { 329 | devices.deviceList[device_id]["implementation"] = payload; 330 | } else if (topic[1] === "$extensions") { 331 | devices.deviceList[device_id]["extensions"] = payload.split(","); 332 | } else if (topic[1] === "$fw") { 333 | if (topic[2] === "name") { 334 | devices.deviceList[device_id]["fw_name"] = payload; 335 | } else if (topic[2] === "version") { 336 | devices.deviceList[device_id]["fw_version"] = payload; 337 | } 338 | } else if (topic[1] === "$stats") { 339 | if (topic[2] === "uptime") { 340 | devices.deviceList[device_id]["stats_uptime"] = payload; 341 | } else if (topic[2] === "interval") { 342 | devices.deviceList[device_id]["stats_interval"] = payload; 343 | } else if (topic[2] === "freeheap") { 344 | devices.deviceList[device_id]["stats_freeheap"] = payload; 345 | } else if (topic[2] === "signal") { 346 | devices.deviceList[device_id]["stats_signal"] = payload; 347 | } 348 | } else if (topic[1] === "$nodes") { 349 | // add nodes to device object 350 | var nodes = payload.split(","); 351 | for (n in nodes) { 352 | // Don't add the node if it's already there, to avoid unnecessary UI updates. 353 | if (nodes[n] in devices.deviceList[device_id].nodes) { 354 | continue; 355 | } 356 | // devices.$set(devices.deviceList.nodes, node, {}); 357 | devices.$set(devices.deviceList[device_id].nodes, nodes[n], { 358 | id: nodes[n], 359 | name: "", 360 | type: "", 361 | properties: {} 362 | }); 363 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/${nodes[n]}/$name`); 364 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/${nodes[n]}/$type`); 365 | subscribe( 366 | device_id, 367 | `${BASE_TOPIC}/${topic[0]}/${nodes[n]}/$properties` 368 | ); 369 | } 370 | // Remove old nodes from device object. 371 | for (n in devices.deviceList[device_id].nodes) { 372 | if (!nodes.includes(n)){ 373 | devices.$delete(devices.deviceList[device_id].nodes, n); 374 | unsubscribePrefix(device_id, `${BASE_TOPIC}/${topic[0]}/${nodes[n]}/`); 375 | } 376 | } 377 | } else if (topic[1] in devices.deviceList[device_id]["nodes"]) { 378 | // add attributes to node 379 | var node = topic[1]; 380 | 381 | if (topic[2] === "$name") { 382 | devices.deviceList[device_id]["nodes"][node]["name"] = payload; 383 | } else if (topic[2] === "$type") { 384 | devices.deviceList[device_id]["nodes"][node]["type"] = payload; 385 | } else if (topic[2] === "$properties") { 386 | var properties = payload.split(","); 387 | for (p in properties) { 388 | devices.$set( 389 | devices.deviceList[device_id].nodes[node].properties, 390 | properties[p], 391 | { 392 | id: properties[p], 393 | name: properties[p], 394 | settable: "false", 395 | datatype: "string", 396 | format: "", 397 | retained: "true", 398 | unit: "", 399 | state: "", 400 | topic: `${BASE_TOPIC}/${topic[0]}/${topic[1]}/${properties[p]}` 401 | } 402 | ); 403 | subscribe( 404 | device_id, 405 | `${BASE_TOPIC}/${topic[0]}/${topic[1]}/${properties[p]}/#` 406 | ); 407 | } 408 | } else if ( 409 | topic[2] in devices.deviceList[device_id]["nodes"][node]["properties"] 410 | ) { 411 | property = topic[2]; 412 | if (topic.length === 3) { 413 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 414 | "state" 415 | ] = payload; 416 | } else if (topic[3] === "$name") { 417 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 418 | "name" 419 | ] = payload; 420 | } else if (topic[3] === "$settable") { 421 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 422 | "settable" 423 | ] = payload; 424 | } else if (topic[3] === "$datatype") { 425 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 426 | "datatype" 427 | ] = payload; 428 | } else if (topic[3] === "$format") { 429 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 430 | "format" 431 | ] = payload; 432 | } else if (topic[3] === "$retained") { 433 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 434 | "retained" 435 | ] = payload; 436 | } else if (topic[3] === "$unit") { 437 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 438 | "unit" 439 | ] = payload; 440 | } 441 | } 442 | } 443 | } 444 | } 445 | -------------------------------------------------------------------------------- /js/app_slim.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * HoDD v0.4.0 3 | Homie Device Discovery 4 | * (c) 2019 Rafael Römhild 5 | * Released under the MIT License. 6 | */ 7 | 8 | var deviceTopics = {}; 9 | var deviceSubscriptions = {}; 10 | var colorPicker = VueColor.Compact; 11 | 12 | // MQTT client 13 | var BASE_TOPIC = "homie"; 14 | var DISCOVERY_TOPIC = `${BASE_TOPIC}/+/$homie`; 15 | var client = new Paho.Client("localhost", 8084, clientId()); 16 | 17 | // vue 18 | var devices = new Vue({ 19 | el: "#app", 20 | data: { 21 | deviceList: {} 22 | }, 23 | components: { "color-picker": colorPicker }, 24 | methods: { 25 | updateProperty: function(topic, event) { 26 | var set_topic = topic + "/set"; 27 | message = new Paho.Message(event); 28 | message.destinationName = set_topic; 29 | message.retained = false; 30 | message.qos = 1; 31 | client.send(message); 32 | }, 33 | badge_appearance: function(state) { 34 | if (state === "init") { 35 | return "info"; 36 | } else if (state === "ready") { 37 | return "success"; 38 | } else if (state === "lost") { 39 | return "warning"; 40 | } else if (state === "disconnected") { 41 | return "secondary"; 42 | } else if (state === "sleeping") { 43 | return "primary"; 44 | } else if (state === "alert") { 45 | return "danger"; 46 | } 47 | }, 48 | timeSince: function(secs) { 49 | var t = new Date(1970, 0, 1); 50 | t.setSeconds(secs); 51 | var s = t.toTimeString().substr(0, 8); 52 | if (secs > 86399) 53 | s = Math.floor((t - Date.parse("1/1/70")) / 3600000) + s.substr(2); 54 | return s; 55 | }, 56 | wipeDevice: function(deviceId) { 57 | // unsubscribe from topics 58 | for (var i = 0; i < deviceSubscriptions[deviceId].length; i++) { 59 | client.unsubscribe(deviceSubscriptions[deviceId][i]); 60 | } 61 | // remove all retained messages from topics 62 | for (var i = 0; i < deviceTopics[deviceId].length; i++) { 63 | message = new Paho.Message(""); 64 | message.destinationName = deviceTopics[deviceId][i]; 65 | message.retained = true; 66 | client.send(message); 67 | } 68 | 69 | // remove device from objects 70 | delete this.deviceList[deviceId]; 71 | delete deviceTopics[deviceId]; 72 | delete deviceSubscriptions[deviceId]; 73 | 74 | // update view 75 | this.$forceUpdate(); 76 | }, 77 | formatToArray: function(csv) { 78 | // comma seperated value 79 | var new_array = csv.split(","); 80 | return new_array; 81 | }, 82 | stringToRGB: function(v) { 83 | var rgb = v.split(","); 84 | return { r: parseInt(rgb[0]), g: parseInt(rgb[1]), b: parseInt(rgb[2]) }; 85 | }, 86 | updateRGBColor: function(t, v) { 87 | var colorString = v.rgba.r + "," + v.rgba.g + "," + v.rgba.b; 88 | var set_topic = t + "/set"; 89 | message = new Paho.Message(colorString); 90 | message.destinationName = set_topic; 91 | message.retained = false; 92 | client.send(message); 93 | }, 94 | doCopy: function(t, v) { 95 | this.$copyText(t); 96 | }, 97 | mpyCommand: function(t, v) { 98 | message = new Paho.Message(v); 99 | message.destinationName = t + "/$mpy"; 100 | message.retained = false; 101 | client.send(message); 102 | }, 103 | showDeviceModal(device) { 104 | // subscribe to device topics 105 | subscribe(device.id, `${device.topic}/+`); 106 | subscribe(device.id, `${device.topic}/$fw/+`); 107 | subscribe(device.id, `${device.topic}/$stats/+`); 108 | 109 | this.$bvModal.show(device.id); 110 | } 111 | } 112 | }); 113 | 114 | var client_status = new Vue({ 115 | el: "#client_status", 116 | data: { 117 | connected: false, 118 | message: "disconnected", 119 | broker: "localhost", 120 | port: 8084, 121 | ssl: "true", 122 | user: "", 123 | pass: "", 124 | reconnect: true, 125 | timeout: 10, 126 | clientId: clientId(), 127 | topic: BASE_TOPIC, 128 | autoConnect: "false" 129 | }, 130 | methods: { 131 | badge_appearance: function(state) { 132 | if (this.connected === true) { 133 | return "success"; 134 | } else { 135 | return "warning"; 136 | } 137 | }, 138 | settingsHandleOK(bvModalEvt) { 139 | BASE_TOPIC = this.topic; 140 | DISCOVERY_TOPIC = `${this.topic}/+/$homie`; 141 | connect_to_mqtt(this); 142 | } 143 | }, 144 | mounted() { 145 | if (localStorage.broker) { 146 | this.broker = localStorage.broker; 147 | } 148 | if (localStorage.user) { 149 | this.user = localStorage.user; 150 | } 151 | if (localStorage.pass) { 152 | this.pass = localStorage.pass; 153 | } 154 | if (localStorage.port) { 155 | this.port = localStorage.port; 156 | } 157 | if (localStorage.ssl) { 158 | this.ssl = localStorage.ssl; 159 | } 160 | if (localStorage.topic) { 161 | this.topic = localStorage.topic; 162 | } 163 | }, 164 | watch: { 165 | broker(newBroker) { 166 | localStorage.broker = newBroker; 167 | }, 168 | user(newUser) { 169 | localStorage.user = newUser; 170 | }, 171 | pass(newPass) { 172 | localStorage.pass = newPass; 173 | }, 174 | port(newPort) { 175 | localStorage.port = newPort; 176 | }, 177 | ssl(newSSL) { 178 | localStorage.ssl = newSSL; 179 | }, 180 | topic(newTopic) { 181 | localStorage.topic = newTopic; 182 | } 183 | } 184 | }); 185 | 186 | // Initiate the mqtt client and connect to mqtt 187 | function connect_to_mqtt(settings) { 188 | // disconnect before re-connect 189 | if (client.isConnected()) { 190 | console.log("Disconnect"); 191 | client.disconnect(); 192 | } 193 | 194 | console.log("Connecting..."); 195 | 196 | var options = { 197 | useSSL: settings.ssl === "true", 198 | onSuccess: onConnect, 199 | onFailure: doFail, 200 | reconnect: true, 201 | timeout: 10 202 | }; 203 | 204 | if (settings.user !== "") { 205 | options.userName = settings.user; 206 | if (settings.pass !== "") { 207 | options.password = settings.pass; 208 | } 209 | } 210 | 211 | // new client instance 212 | client = new Paho.Client( 213 | settings.broker, 214 | Number(settings.port), 215 | settings.clientId 216 | ); 217 | 218 | // set callback handlers 219 | client.onConnectionLost = onConnectionLost; 220 | client.onMessageArrived = onMessageArrived; 221 | 222 | client.connect(options); 223 | } 224 | 225 | // MQTT Client ID 226 | function clientId() { 227 | return ( 228 | "hodd_" + 229 | Math.random() 230 | .toString(16) 231 | .substr(2, 8) 232 | ); 233 | } 234 | 235 | function doFail(e) { 236 | console.log(e); 237 | client_status.connected = false; 238 | client_status.message = "disconnected"; 239 | } 240 | 241 | // called when the client connects 242 | function onConnect() { 243 | client_status.connected = true; 244 | client_status.message = "connected"; 245 | client.subscribe(DISCOVERY_TOPIC); 246 | } 247 | 248 | // called when the client looses its connection 249 | function onConnectionLost(responseObject) { 250 | if (responseObject.errorCode !== 0) { 251 | console.log("onConnectionLost:" + responseObject.errorMessage); 252 | } 253 | client_status.connected = false; 254 | client_status.message = "lost"; 255 | } 256 | 257 | // subscribe to topic and keep that info 258 | function subscribe(deviceId, topic) { 259 | client.subscribe(topic, 1); 260 | deviceSubscriptions[deviceId].push(topic); 261 | } 262 | 263 | // Unsubscribe from all topics to which we have previously subscribed which start with the given 264 | // prefix. 265 | function unsubscribePrefix(deviceId, topicPrefix) { 266 | var remainingSubscripions = []; 267 | for (topic of deviceSubscriptions[deviceId]) { 268 | if (topic.startsWith(topicPrefix)) { 269 | client.unsubscribe(topic); 270 | } else { 271 | remainingSubscripions.push(topic); 272 | } 273 | } 274 | deviceSubscriptions[deviceId] = remainingSubscripions; 275 | } 276 | 277 | // called when a message arrives 278 | function onMessageArrived(message) { 279 | // console.log("onMessageArrived: " + message.topic + " Payload: " + message.payloadString); 280 | 281 | // ignore /set topics 282 | if (message.destinationName.endsWith("/set")) { 283 | return; 284 | } 285 | 286 | var topic = message.destinationName.slice(BASE_TOPIC.length + 1).split("/"); 287 | var payload = message.payloadString; 288 | var device_id = topic[0]; 289 | 290 | // first message; add device to device list 291 | if (!(device_id in devices.deviceList)) { 292 | if (!payload) { 293 | return; 294 | } 295 | 296 | // add topic to deviceTopics 297 | deviceTopics[device_id] = [message.destinationName]; 298 | deviceSubscriptions[device_id] = []; 299 | 300 | devices.$set(devices.deviceList, device_id, { 301 | id: device_id, 302 | homie: payload, 303 | name: "", 304 | state: "", 305 | localip: "", 306 | mac: "", 307 | fw_name: "", 308 | fw_version: "", 309 | stats_interval: "", 310 | stats_uptime: "", 311 | stats_freeheap: "", 312 | implementation: "", 313 | nodes: {}, 314 | topic: `${BASE_TOPIC}/${topic[0]}`, 315 | extensions: [] 316 | }); 317 | 318 | // subscribe to device topics 319 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/$name`); 320 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/$state`); 321 | } else { 322 | // add topic to deviceTopics 323 | deviceTopics[device_id].push(message.destinationName); 324 | 325 | // process attributes and payloads 326 | if (topic[1] === "$name") { 327 | devices.deviceList[device_id]["name"] = payload; 328 | } else if (topic[1] === "$state") { 329 | devices.deviceList[device_id]["state"] = payload; 330 | } else if (topic[1] === "$localip") { 331 | devices.deviceList[device_id]["localip"] = payload; 332 | } else if (topic[1] === "$mac") { 333 | devices.deviceList[device_id]["mac"] = payload; 334 | } else if (topic[1] === "$implementation") { 335 | devices.deviceList[device_id]["implementation"] = payload; 336 | } else if (topic[1] === "$extensions") { 337 | devices.deviceList[device_id]["extensions"] = payload.split(","); 338 | } else if (topic[1] === "$fw") { 339 | if (topic[2] === "name") { 340 | devices.deviceList[device_id]["fw_name"] = payload; 341 | } else if (topic[2] === "version") { 342 | devices.deviceList[device_id]["fw_version"] = payload; 343 | } 344 | } else if (topic[1] === "$stats") { 345 | if (topic[2] === "uptime") { 346 | devices.deviceList[device_id]["stats_uptime"] = payload; 347 | } else if (topic[2] === "interval") { 348 | devices.deviceList[device_id]["stats_interval"] = payload; 349 | } else if (topic[2] === "freeheap") { 350 | devices.deviceList[device_id]["stats_freeheap"] = payload; 351 | } 352 | } else if (topic[1] === "$nodes") { 353 | // add nodes to device object 354 | var nodes = payload.split(","); 355 | for (n in nodes) { 356 | // Don't add the node if it's already there, to avoid unnecessary UI updates. 357 | if (nodes[n] in devices.deviceList[device_id].nodes) { 358 | continue; 359 | } 360 | // devices.$set(devices.deviceList.nodes, node, {}); 361 | devices.$set(devices.deviceList[device_id].nodes, nodes[n], { 362 | id: nodes[n], 363 | name: "", 364 | type: "", 365 | properties: {} 366 | }); 367 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/${nodes[n]}/$name`); 368 | subscribe(device_id, `${BASE_TOPIC}/${topic[0]}/${nodes[n]}/$type`); 369 | subscribe( 370 | device_id, 371 | `${BASE_TOPIC}/${topic[0]}/${nodes[n]}/$properties` 372 | ); 373 | } 374 | // Remove old nodes from device object. 375 | for (n in devices.deviceList[device_id].nodes) { 376 | if (!nodes.includes(n)){ 377 | devices.$delete(devices.deviceList[device_id].nodes, n); 378 | unsubscribePrefix(device_id, `${BASE_TOPIC}/${topic[0]}/${nodes[n]}/`); 379 | } 380 | } 381 | } else if (topic[1] in devices.deviceList[device_id]["nodes"]) { 382 | // add attributes to node 383 | var node = topic[1]; 384 | 385 | if (topic[2] === "$name") { 386 | devices.deviceList[device_id]["nodes"][node]["name"] = payload; 387 | } else if (topic[2] === "$type") { 388 | devices.deviceList[device_id]["nodes"][node]["type"] = payload; 389 | } else if (topic[2] === "$properties") { 390 | var properties = payload.split(","); 391 | for (p in properties) { 392 | devices.$set( 393 | devices.deviceList[device_id].nodes[node].properties, 394 | properties[p], 395 | { 396 | id: properties[p], 397 | name: "", 398 | settable: "false", 399 | datatype: "string", 400 | format: "", 401 | retained: "true", 402 | unit: "", 403 | state: "", 404 | topic: `${BASE_TOPIC}/${topic[0]}/${topic[1]}/${properties[p]}` 405 | } 406 | ); 407 | subscribe( 408 | device_id, 409 | `${BASE_TOPIC}/${topic[0]}/${topic[1]}/${properties[p]}/#` 410 | ); 411 | } 412 | } else if ( 413 | topic[2] in devices.deviceList[device_id]["nodes"][node]["properties"] 414 | ) { 415 | property = topic[2]; 416 | if (topic.length === 3) { 417 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 418 | "state" 419 | ] = payload; 420 | } else if (topic[3] === "$name") { 421 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 422 | "name" 423 | ] = payload; 424 | } else if (topic[3] === "$settable") { 425 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 426 | "settable" 427 | ] = payload; 428 | } else if (topic[3] === "$datatype") { 429 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 430 | "datatype" 431 | ] = payload; 432 | } else if (topic[3] === "$format") { 433 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 434 | "format" 435 | ] = payload; 436 | } else if (topic[3] === "$retained") { 437 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 438 | "retained" 439 | ] = payload; 440 | } else if (topic[3] === "$unit") { 441 | devices.deviceList[device_id]["nodes"][node]["properties"][property][ 442 | "unit" 443 | ] = payload; 444 | } 445 | } 446 | } 447 | } 448 | } 449 | -------------------------------------------------------------------------------- /js/popper.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) Federico Zivolo 2019 3 | Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). 4 | */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=e.ownerDocument.defaultView,n=o.getComputedStyle(e,null);return t?n[t]:n}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function r(e){return 11===e?pe:10===e?se:pe||se}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent||null;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TH','TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),le({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=fe({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f],10),E=parseFloat(w['border'+f+'Width'],10),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},le(n,m,$(v)),le(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ge.FLIP:p=[n,i];break;case ge.CLOCKWISE:p=G(n);break;case ge.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u),E=!!t.flipVariationsByContent&&(w&&'start'===r&&c||w&&'end'===r&&h||!w&&'start'===r&&u||!w&&'end'===r&&g),v=y||E;(m||b||v)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),v&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=fe({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport',flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.rightwindow.devicePixelRatio||!me),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=B('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=fe({},E,e.attributes),e.styles=fe({},m,e.styles),e.arrowStyles=fe({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return V(e.instance.popper,e.styles),j(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&V(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),V(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ue}); 5 | //# sourceMappingURL=popper.min.js.map 6 | -------------------------------------------------------------------------------- /js/paho-mqtt.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2013, 2016 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | *******************************************************************************/ 14 | (function(t,q){"object"===typeof exports&&"object"===typeof module?module.exports=q():"function"===typeof define&&define.amd?define(q):"object"===typeof exports?exports=q():t.Paho=q()})(this,function(){return function(t){function q(a,b,c){b[c++]=a>>8;b[c++]=a%256;return c}function r(a,b,c,k){k=q(b,c,k);E(a,c,k);return k+b}function n(a){for(var b=0,c=0;c=k&&(c++,b++),b+=3):127=e){var g=a.charCodeAt(++k);if(isNaN(g))throw Error(f(h.MALFORMED_UNICODE,[e,g]));e=(e-55296<<10)+(g-56320)+65536}127>=e?b[c++]=e:(2047>=e?b[c++]=e>>6&31|192:(65535>=e?b[c++]=e>>12&15|224:(b[c++]=e>>18&7|240,b[c++]=e>>12&63|128),b[c++]=e>>6&63|128),b[c++]=e&63|128)}return b}function F(a,b,c){for(var k="",e,g=b;ge)){var m=a[g++]-128;if(0>m)throw Error(f(h.MALFORMED_UTF,[e.toString(16),m.toString(16),""]));if(224>e)e=64*(e-192)+m;else{var d= 16 | a[g++]-128;if(0>d)throw Error(f(h.MALFORMED_UTF,[e.toString(16),m.toString(16),d.toString(16)]));if(240>e)e=4096*(e-224)+64*m+d;else{var l=a[g++]-128;if(0>l)throw Error(f(h.MALFORMED_UTF,[e.toString(16),m.toString(16),d.toString(16),l.toString(16)]));if(248>e)e=262144*(e-240)+4096*m+64*d+l;else throw Error(f(h.MALFORMED_UTF,[e.toString(16),m.toString(16),d.toString(16),l.toString(16)]));}}}65535>10)),e=56320+(e&1023));k+=String.fromCharCode(e)}return k} 17 | var s=t.localStorage||function(){var a={};return{setItem:function(b,c){a[b]=c},getItem:function(b){return a[b]},removeItem:function(b){delete a[b]}}}(),A=function(a,b){for(var c in a)if(a.hasOwnProperty(c))if(b.hasOwnProperty(c)){if(typeof a[c]!==b[c])throw Error(f(h.INVALID_TYPE,[typeof a[c],c]));}else{c="Unknown property, "+c+". Valid properties are:";for(var k in b)b.hasOwnProperty(k)&&(c=c+" "+k);throw Error(c);}},u=function(a,b){return function(){return a.apply(b,arguments)}},h={OK:{code:0,text:"AMQJSC0000I OK."}, 18 | CONNECT_TIMEOUT:{code:1,text:"AMQJSC0001E Connect timed out."},SUBSCRIBE_TIMEOUT:{code:2,text:"AMQJS0002E Subscribe timed out."},UNSUBSCRIBE_TIMEOUT:{code:3,text:"AMQJS0003E Unsubscribe timed out."},PING_TIMEOUT:{code:4,text:"AMQJS0004E Ping timed out."},INTERNAL_ERROR:{code:5,text:"AMQJS0005E Internal error. Error Message: {0}, Stack trace: {1}"},CONNACK_RETURNCODE:{code:6,text:"AMQJS0006E Bad Connack return code:{0} {1}."},SOCKET_ERROR:{code:7,text:"AMQJS0007E Socket error:{0}."},SOCKET_CLOSE:{code:8, 19 | text:"AMQJS0008I Socket closed."},MALFORMED_UTF:{code:9,text:"AMQJS0009E Malformed UTF data:{0} {1} {2}."},UNSUPPORTED:{code:10,text:"AMQJS0010E {0} is not supported by this browser."},INVALID_STATE:{code:11,text:"AMQJS0011E Invalid state {0}."},INVALID_TYPE:{code:12,text:"AMQJS0012E Invalid type {0} for {1}."},INVALID_ARGUMENT:{code:13,text:"AMQJS0013E Invalid argument {0} for {1}."},UNSUPPORTED_OPERATION:{code:14,text:"AMQJS0014E Unsupported operation."},INVALID_STORED_DATA:{code:15,text:"AMQJS0015E Invalid data in local storage key\x3d{0} value\x3d{1}."}, 20 | INVALID_MQTT_MESSAGE_TYPE:{code:16,text:"AMQJS0016E Invalid MQTT message type {0}."},MALFORMED_UNICODE:{code:17,text:"AMQJS0017E Malformed Unicode string:{0} {1}."},BUFFER_FULL:{code:18,text:"AMQJS0018E Message buffer is full, maximum buffer size: {0}."}},H={0:"Connection Accepted",1:"Connection Refused: unacceptable protocol version",2:"Connection Refused: identifier rejected",3:"Connection Refused: server unavailable",4:"Connection Refused: bad user name or password",5:"Connection Refused: not authorized"}, 21 | f=function(a,b){var c=a.text;if(b)for(var k,e,g=0;g>7;0d);f=g.length+1;b=new ArrayBuffer(b+f);d=new Uint8Array(b);d[0]=a;d.set(g,1);if(3==this.type)f=r(this.payloadMessage.destinationName, 24 | k,d,f);else if(1==this.type){switch(this.mqttVersion){case 3:d.set(B,f);f+=B.length;break;case 4:d.set(C,f),f+=C.length}a=0;this.cleanSession&&(a=2);void 0!==this.willMessage&&(a=a|4|this.willMessage.qos<<3,this.willMessage.retained&&(a|=32));void 0!==this.userName&&(a|=128);void 0!==this.password&&(a|=64);d[f++]=a;f=q(this.keepAliveInterval,d,f)}void 0!==this.messageIdentifier&&(f=q(this.messageIdentifier,d,f));switch(this.type){case 1:f=r(this.clientId,n(this.clientId),d,f);void 0!==this.willMessage&& 25 | (f=r(this.willMessage.destinationName,n(this.willMessage.destinationName),d,f),f=q(e.byteLength,d,f),d.set(e,f),f+=e.byteLength);void 0!==this.userName&&(f=r(this.userName,n(this.userName),d,f));void 0!==this.password&&r(this.password,n(this.password),d,f);break;case 3:d.set(h,f);break;case 8:for(g=0;gthis.disconnectedBufferSize)throw Error(f(h.BUFFER_FULL,[this.disconnectedBufferSize]));0this.connectOptions.mqttVersion?new WebSocket(a,["mqttv3.1"]):new WebSocket(a,["mqtt"]);this.socket.binaryType="arraybuffer";this.socket.onopen=u(this._on_socket_open,this);this.socket.onmessage=u(this._on_socket_message,this);this.socket.onerror=u(this._on_socket_error,this);this.socket.onclose=u(this._on_socket_close, 38 | this);this.sendPinger=new G(this,this.connectOptions.keepAliveInterval);this.receivePinger=new G(this,this.connectOptions.keepAliveInterval);this._connectTimeout&&(this._connectTimeout.cancel(),this._connectTimeout=null);this._connectTimeout=new v(this,this.connectOptions.timeout,this._disconnected,[h.CONNECT_TIMEOUT.code,f(h.CONNECT_TIMEOUT)])};d.prototype._schedule_message=function(a){this._msg_queue.unshift(a);this.connected&&this._process_queue()};d.prototype.store=function(a,b){var c={type:b.type, 39 | messageIdentifier:b.messageIdentifier,version:1};switch(b.type){case 3:b.pubRecReceived&&(c.pubRecReceived=!0);c.payloadMessage={};for(var d="",e=b.payloadMessage.payloadBytes,g=0;g=e[g]?d+"0"+e[g].toString(16):d+e[g].toString(16);c.payloadMessage.payloadHex=d;c.payloadMessage.qos=b.payloadMessage.qos;c.payloadMessage.destinationName=b.payloadMessage.destinationName;b.payloadMessage.duplicate&&(c.payloadMessage.duplicate=!0);b.payloadMessage.retained&&(c.payloadMessage.retained= 40 | !0);0===a.indexOf("Sent:")&&(void 0===b.sequence&&(b.sequence=++this._sequence),c.sequence=b.sequence);break;default:throw Error(f(h.INVALID_STORED_DATA,[a+this._localKey+b.messageIdentifier,c]));}s.setItem(a+this._localKey+b.messageIdentifier,JSON.stringify(c))};d.prototype.restore=function(a){var b=s.getItem(a),c=JSON.parse(b),d=new p(c.type,c);switch(c.type){case 3:for(var b=c.payloadMessage.payloadHex,e=new ArrayBuffer(b.length/2),e=new Uint8Array(e),g=0;2<=b.length;){var m=parseInt(b.substring(0, 41 | 2),16),b=b.substring(2,b.length);e[g++]=m}b=new w(e);b.qos=c.payloadMessage.qos;b.destinationName=c.payloadMessage.destinationName;c.payloadMessage.duplicate&&(b.duplicate=!0);c.payloadMessage.retained&&(b.retained=!0);d.payloadMessage=b;break;default:throw Error(f(h.INVALID_STORED_DATA,[a,b]));}0===a.indexOf("Sent:"+this._localKey)?(d.payloadMessage.duplicate=!0,this._sentMessages[d.messageIdentifier]=d):0===a.indexOf("Received:"+this._localKey)&&(this._receivedMessages[d.messageIdentifier]=d)}; 42 | d.prototype._process_queue=function(){for(var a=null;a=this._msg_queue.pop();)this._socket_send(a),this._notify_msg_sent[a]&&(this._notify_msg_sent[a](),delete this._notify_msg_sent[a])};d.prototype._requires_ack=function(a){var b=Object.keys(this._sentMessages).length;if(b>this.maxMessageIdentifier)throw Error("Too many messages:"+b);for(;void 0!==this._sentMessages[this._message_identifier];)this._message_identifier++;a.messageIdentifier=this._message_identifier;this._sentMessages[a.messageIdentifier]= 43 | a;3===a.type&&this.store("Sent:",a);this._message_identifier===this.maxMessageIdentifier&&(this._message_identifier=1)};d.prototype._on_socket_open=function(){var a=new p(1,this.connectOptions);a.clientId=this.clientId;this._socket_send(a)};d.prototype._on_socket_message=function(a){this._trace("Client._on_socket_message",a.data);a=this._deframeMessages(a.data);for(var b=0;b>4,z=n&15,g=g+1,x=void 0,D=0,q=1;do{if(g==e.length){d=[null,m];break a}x=e[g++];D+=(x&127)*q;q*=128}while(0!==(x&128));x=g+D;if(x>e.length)d=[null,m];else{var y=new p(l);switch(l){case 2:e[g++]&1&&(y.sessionPresent=!0);y.returnCode=e[g++];break;case 3:var m=z>>1&3,s=256*e[g]+e[g+1],g=g+2,t=F(e,g,s), 45 | g=g+s;0this._reconnectInterval&&(this._reconnectInterval*=2),this.connectOptions.uris?(this.hostIndex=0,this._doConnect(this.connectOptions.uris[0])):this._doConnect(this.uri))};d.prototype._disconnected=function(a,b){this._trace("Client._disconnected",a,b);if(void 0!==a&&this._reconnecting)this._reconnectTimeout=new v(this,this._reconnectInterval,this._reconnect);else if(this.sendPinger.cancel(),this.receivePinger.cancel(),this._connectTimeout&& 56 | (this._connectTimeout.cancel(),this._connectTimeout=null),this._msg_queue=[],this._buffered_msg_queue=[],this._notify_msg_sent={},this.socket&&(this.socket.onopen=null,this.socket.onmessage=null,this.socket.onerror=null,this.socket.onclose=null,1===this.socket.readyState&&this.socket.close(),delete this.socket),this.connectOptions.uris&&this.hostIndexb)throw Error(f(h.INVALID_TYPE,[typeof b,"port"]));if("string"!==typeof c)throw Error(f(h.INVALID_TYPE,[typeof c,"path"]));e="ws://"+(-1!==a.indexOf(":")&&"["!==a.slice(0,1)&&"]"!==a.slice(-1)?"["+a+"]":a)+":"+b+c}for(var m=g=0;m=n&&m++;g++}if("string"!==typeof k||65535a.mqttVersion)throw Error(f(h.INVALID_ARGUMENT,[a.mqttVersion,"connectOptions.mqttVersion"]));void 0===a.mqttVersion?(a.mqttVersionExplicit=!1,a.mqttVersion=4):a.mqttVersionExplicit=!0;if(void 0!==a.password&&void 0===a.userName)throw Error(f(h.INVALID_ARGUMENT,[a.password,"connectOptions.password"]));if(a.willMessage){if(!(a.willMessage instanceof 68 | w))throw Error(f(h.INVALID_TYPE,[a.willMessage,"connectOptions.willMessage"]));a.willMessage.stringPayload=null;if("undefined"===typeof a.willMessage.destinationName)throw Error(f(h.INVALID_TYPE,[typeof a.willMessage.destinationName,"connectOptions.willMessage.destinationName"]));}"undefined"===typeof a.cleanSession&&(a.cleanSession=!0);if(a.hosts){if(!(a.hosts instanceof Array))throw Error(f(h.INVALID_ARGUMENT,[a.hosts,"connectOptions.hosts"]));if(1>a.hosts.length)throw Error(f(h.INVALID_ARGUMENT, 69 | [a.hosts,"connectOptions.hosts"]));for(var b=!1,d=0;da.ports[d])throw Error(f(h.INVALID_TYPE,[typeof a.ports[d],"connectOptions.ports["+d+"]"]));var b=a.hosts[d],g=a.ports[d];e="ws://"+(-1!==b.indexOf(":")?"["+b+"]":b)+":"+g+c;a.uris.push(e)}}}l.connect(a)}; 71 | this.subscribe=function(a,b){if("string"!==typeof a&&a.constructor!==Array)throw Error("Invalid argument:"+a);b=b||{};A(b,{qos:"number",invocationContext:"object",onSuccess:"function",onFailure:"function",timeout:"number"});if(b.timeout&&!b.onFailure)throw Error("subscribeOptions.timeout specified with no onFailure callback.");if("undefined"!==typeof b.qos&&0!==b.qos&&1!==b.qos&&2!==b.qos)throw Error(f(h.INVALID_ARGUMENT,[b.qos,"subscribeOptions.qos"]));l.subscribe(a,b)};this.unsubscribe=function(a, 72 | b){if("string"!==typeof a&&a.constructor!==Array)throw Error("Invalid argument:"+a);b=b||{};A(b,{invocationContext:"object",onSuccess:"function",onFailure:"function",timeout:"number"});if(b.timeout&&!b.onFailure)throw Error("unsubscribeOptions.timeout specified with no onFailure callback.");l.unsubscribe(a,b)};this.send=function(a,b,c,d){var e;if(0===arguments.length)throw Error("Invalid argument.length");if(1==arguments.length){if(!(a instanceof w)&&"string"!==typeof a)throw Error("Invalid argument:"+ 73 | typeof a);e=a;if("undefined"===typeof e.destinationName)throw Error(f(h.INVALID_ARGUMENT,[e.destinationName,"Message.destinationName"]));}else e=new w(b),e.destinationName=a,3<=arguments.length&&(e.qos=c),4<=arguments.length&&(e.retained=d);l.send(e)};this.publish=function(a,b,c,d){var e;if(0===arguments.length)throw Error("Invalid argument.length");if(1==arguments.length){if(!(a instanceof w)&&"string"!==typeof a)throw Error("Invalid argument:"+typeof a);e=a;if("undefined"===typeof e.destinationName)throw Error(f(h.INVALID_ARGUMENT, 74 | [e.destinationName,"Message.destinationName"]));}else e=new w(b),e.destinationName=a,3<=arguments.length&&(e.qos=c),4<=arguments.length&&(e.retained=d);l.send(e)};this.disconnect=function(){l.disconnect()};this.getTraceLog=function(){return l.getTraceLog()};this.startTrace=function(){l.startTrace()};this.stopTrace=function(){l.stopTrace()};this.isConnected=function(){return l.connected}},Message:w}}("undefined"!==typeof global?global:"undefined"!==typeof self?self:"undefined"!==typeof window?window: 75 | {})}); 76 | -------------------------------------------------------------------------------- /css/ionicons.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | Ionicons, v4.5.9-1 3 | Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ 4 | https://twitter.com/benjsperry https://twitter.com/ionicframework 5 | MIT License: https://github.com/driftyco/ionicons 6 | 7 | Android-style icons originally built by Google’s 8 | Material Design Icons: https://github.com/google/material-design-icons 9 | used under CC BY http://creativecommons.org/licenses/by/4.0/ 10 | Modified icons to fit ionicon’s grid from original. 11 | */@font-face{font-family:"Ionicons";src:url("../fonts/ionicons.eot?v=4.5.9-1");src:url("../fonts/ionicons.eot?v=4.5.9-1#iefix") format("embedded-opentype"),url("../fonts/ionicons.woff2?v=4.5.9-1") format("woff2"),url("../fonts/ionicons.woff?v=4.5.9-1") format("woff"),url("../fonts/ionicons.ttf?v=4.5.9-1") format("truetype"),url("../fonts/ionicons.svg?v=4.5.9-1#Ionicons") format("svg");font-weight:normal;font-style:normal}.ion,.ionicons,.ion-ios-add:before,.ion-ios-add-circle:before,.ion-ios-add-circle-outline:before,.ion-ios-airplane:before,.ion-ios-alarm:before,.ion-ios-albums:before,.ion-ios-alert:before,.ion-ios-american-football:before,.ion-ios-analytics:before,.ion-ios-aperture:before,.ion-ios-apps:before,.ion-ios-appstore:before,.ion-ios-archive:before,.ion-ios-arrow-back:before,.ion-ios-arrow-down:before,.ion-ios-arrow-dropdown:before,.ion-ios-arrow-dropdown-circle:before,.ion-ios-arrow-dropleft:before,.ion-ios-arrow-dropleft-circle:before,.ion-ios-arrow-dropright:before,.ion-ios-arrow-dropright-circle:before,.ion-ios-arrow-dropup:before,.ion-ios-arrow-dropup-circle:before,.ion-ios-arrow-forward:before,.ion-ios-arrow-round-back:before,.ion-ios-arrow-round-down:before,.ion-ios-arrow-round-forward:before,.ion-ios-arrow-round-up:before,.ion-ios-arrow-up:before,.ion-ios-at:before,.ion-ios-attach:before,.ion-ios-backspace:before,.ion-ios-barcode:before,.ion-ios-baseball:before,.ion-ios-basket:before,.ion-ios-basketball:before,.ion-ios-battery-charging:before,.ion-ios-battery-dead:before,.ion-ios-battery-full:before,.ion-ios-beaker:before,.ion-ios-bed:before,.ion-ios-beer:before,.ion-ios-bicycle:before,.ion-ios-bluetooth:before,.ion-ios-boat:before,.ion-ios-body:before,.ion-ios-bonfire:before,.ion-ios-book:before,.ion-ios-bookmark:before,.ion-ios-bookmarks:before,.ion-ios-bowtie:before,.ion-ios-briefcase:before,.ion-ios-browsers:before,.ion-ios-brush:before,.ion-ios-bug:before,.ion-ios-build:before,.ion-ios-bulb:before,.ion-ios-bus:before,.ion-ios-business:before,.ion-ios-cafe:before,.ion-ios-calculator:before,.ion-ios-calendar:before,.ion-ios-call:before,.ion-ios-camera:before,.ion-ios-car:before,.ion-ios-card:before,.ion-ios-cart:before,.ion-ios-cash:before,.ion-ios-cellular:before,.ion-ios-chatboxes:before,.ion-ios-chatbubbles:before,.ion-ios-checkbox:before,.ion-ios-checkbox-outline:before,.ion-ios-checkmark:before,.ion-ios-checkmark-circle:before,.ion-ios-checkmark-circle-outline:before,.ion-ios-clipboard:before,.ion-ios-clock:before,.ion-ios-close:before,.ion-ios-close-circle:before,.ion-ios-close-circle-outline:before,.ion-ios-cloud:before,.ion-ios-cloud-circle:before,.ion-ios-cloud-done:before,.ion-ios-cloud-download:before,.ion-ios-cloud-outline:before,.ion-ios-cloud-upload:before,.ion-ios-cloudy:before,.ion-ios-cloudy-night:before,.ion-ios-code:before,.ion-ios-code-download:before,.ion-ios-code-working:before,.ion-ios-cog:before,.ion-ios-color-fill:before,.ion-ios-color-filter:before,.ion-ios-color-palette:before,.ion-ios-color-wand:before,.ion-ios-compass:before,.ion-ios-construct:before,.ion-ios-contact:before,.ion-ios-contacts:before,.ion-ios-contract:before,.ion-ios-contrast:before,.ion-ios-copy:before,.ion-ios-create:before,.ion-ios-crop:before,.ion-ios-cube:before,.ion-ios-cut:before,.ion-ios-desktop:before,.ion-ios-disc:before,.ion-ios-document:before,.ion-ios-done-all:before,.ion-ios-download:before,.ion-ios-easel:before,.ion-ios-egg:before,.ion-ios-exit:before,.ion-ios-expand:before,.ion-ios-eye:before,.ion-ios-eye-off:before,.ion-ios-fastforward:before,.ion-ios-female:before,.ion-ios-filing:before,.ion-ios-film:before,.ion-ios-finger-print:before,.ion-ios-fitness:before,.ion-ios-flag:before,.ion-ios-flame:before,.ion-ios-flash:before,.ion-ios-flash-off:before,.ion-ios-flashlight:before,.ion-ios-flask:before,.ion-ios-flower:before,.ion-ios-folder:before,.ion-ios-folder-open:before,.ion-ios-football:before,.ion-ios-funnel:before,.ion-ios-gift:before,.ion-ios-git-branch:before,.ion-ios-git-commit:before,.ion-ios-git-compare:before,.ion-ios-git-merge:before,.ion-ios-git-network:before,.ion-ios-git-pull-request:before,.ion-ios-glasses:before,.ion-ios-globe:before,.ion-ios-grid:before,.ion-ios-hammer:before,.ion-ios-hand:before,.ion-ios-happy:before,.ion-ios-headset:before,.ion-ios-heart:before,.ion-ios-heart-dislike:before,.ion-ios-heart-empty:before,.ion-ios-heart-half:before,.ion-ios-help:before,.ion-ios-help-buoy:before,.ion-ios-help-circle:before,.ion-ios-help-circle-outline:before,.ion-ios-home:before,.ion-ios-hourglass:before,.ion-ios-ice-cream:before,.ion-ios-image:before,.ion-ios-images:before,.ion-ios-infinite:before,.ion-ios-information:before,.ion-ios-information-circle:before,.ion-ios-information-circle-outline:before,.ion-ios-jet:before,.ion-ios-journal:before,.ion-ios-key:before,.ion-ios-keypad:before,.ion-ios-laptop:before,.ion-ios-leaf:before,.ion-ios-link:before,.ion-ios-list:before,.ion-ios-list-box:before,.ion-ios-locate:before,.ion-ios-lock:before,.ion-ios-log-in:before,.ion-ios-log-out:before,.ion-ios-magnet:before,.ion-ios-mail:before,.ion-ios-mail-open:before,.ion-ios-mail-unread:before,.ion-ios-male:before,.ion-ios-man:before,.ion-ios-map:before,.ion-ios-medal:before,.ion-ios-medical:before,.ion-ios-medkit:before,.ion-ios-megaphone:before,.ion-ios-menu:before,.ion-ios-mic:before,.ion-ios-mic-off:before,.ion-ios-microphone:before,.ion-ios-moon:before,.ion-ios-more:before,.ion-ios-move:before,.ion-ios-musical-note:before,.ion-ios-musical-notes:before,.ion-ios-navigate:before,.ion-ios-notifications:before,.ion-ios-notifications-off:before,.ion-ios-notifications-outline:before,.ion-ios-nuclear:before,.ion-ios-nutrition:before,.ion-ios-open:before,.ion-ios-options:before,.ion-ios-outlet:before,.ion-ios-paper:before,.ion-ios-paper-plane:before,.ion-ios-partly-sunny:before,.ion-ios-pause:before,.ion-ios-paw:before,.ion-ios-people:before,.ion-ios-person:before,.ion-ios-person-add:before,.ion-ios-phone-landscape:before,.ion-ios-phone-portrait:before,.ion-ios-photos:before,.ion-ios-pie:before,.ion-ios-pin:before,.ion-ios-pint:before,.ion-ios-pizza:before,.ion-ios-planet:before,.ion-ios-play:before,.ion-ios-play-circle:before,.ion-ios-podium:before,.ion-ios-power:before,.ion-ios-pricetag:before,.ion-ios-pricetags:before,.ion-ios-print:before,.ion-ios-pulse:before,.ion-ios-qr-scanner:before,.ion-ios-quote:before,.ion-ios-radio:before,.ion-ios-radio-button-off:before,.ion-ios-radio-button-on:before,.ion-ios-rainy:before,.ion-ios-recording:before,.ion-ios-redo:before,.ion-ios-refresh:before,.ion-ios-refresh-circle:before,.ion-ios-remove:before,.ion-ios-remove-circle:before,.ion-ios-remove-circle-outline:before,.ion-ios-reorder:before,.ion-ios-repeat:before,.ion-ios-resize:before,.ion-ios-restaurant:before,.ion-ios-return-left:before,.ion-ios-return-right:before,.ion-ios-reverse-camera:before,.ion-ios-rewind:before,.ion-ios-ribbon:before,.ion-ios-rocket:before,.ion-ios-rose:before,.ion-ios-sad:before,.ion-ios-save:before,.ion-ios-school:before,.ion-ios-search:before,.ion-ios-send:before,.ion-ios-settings:before,.ion-ios-share:before,.ion-ios-share-alt:before,.ion-ios-shirt:before,.ion-ios-shuffle:before,.ion-ios-skip-backward:before,.ion-ios-skip-forward:before,.ion-ios-snow:before,.ion-ios-speedometer:before,.ion-ios-square:before,.ion-ios-square-outline:before,.ion-ios-star:before,.ion-ios-star-half:before,.ion-ios-star-outline:before,.ion-ios-stats:before,.ion-ios-stopwatch:before,.ion-ios-subway:before,.ion-ios-sunny:before,.ion-ios-swap:before,.ion-ios-switch:before,.ion-ios-sync:before,.ion-ios-tablet-landscape:before,.ion-ios-tablet-portrait:before,.ion-ios-tennisball:before,.ion-ios-text:before,.ion-ios-thermometer:before,.ion-ios-thumbs-down:before,.ion-ios-thumbs-up:before,.ion-ios-thunderstorm:before,.ion-ios-time:before,.ion-ios-timer:before,.ion-ios-today:before,.ion-ios-train:before,.ion-ios-transgender:before,.ion-ios-trash:before,.ion-ios-trending-down:before,.ion-ios-trending-up:before,.ion-ios-trophy:before,.ion-ios-tv:before,.ion-ios-umbrella:before,.ion-ios-undo:before,.ion-ios-unlock:before,.ion-ios-videocam:before,.ion-ios-volume-high:before,.ion-ios-volume-low:before,.ion-ios-volume-mute:before,.ion-ios-volume-off:before,.ion-ios-walk:before,.ion-ios-wallet:before,.ion-ios-warning:before,.ion-ios-watch:before,.ion-ios-water:before,.ion-ios-wifi:before,.ion-ios-wine:before,.ion-ios-woman:before,.ion-logo-android:before,.ion-logo-angular:before,.ion-logo-apple:before,.ion-logo-bitbucket:before,.ion-logo-bitcoin:before,.ion-logo-buffer:before,.ion-logo-chrome:before,.ion-logo-closed-captioning:before,.ion-logo-codepen:before,.ion-logo-css3:before,.ion-logo-designernews:before,.ion-logo-dribbble:before,.ion-logo-dropbox:before,.ion-logo-euro:before,.ion-logo-facebook:before,.ion-logo-flickr:before,.ion-logo-foursquare:before,.ion-logo-freebsd-devil:before,.ion-logo-game-controller-a:before,.ion-logo-game-controller-b:before,.ion-logo-github:before,.ion-logo-google:before,.ion-logo-googleplus:before,.ion-logo-hackernews:before,.ion-logo-html5:before,.ion-logo-instagram:before,.ion-logo-ionic:before,.ion-logo-ionitron:before,.ion-logo-javascript:before,.ion-logo-linkedin:before,.ion-logo-markdown:before,.ion-logo-model-s:before,.ion-logo-no-smoking:before,.ion-logo-nodejs:before,.ion-logo-npm:before,.ion-logo-octocat:before,.ion-logo-pinterest:before,.ion-logo-playstation:before,.ion-logo-polymer:before,.ion-logo-python:before,.ion-logo-reddit:before,.ion-logo-rss:before,.ion-logo-sass:before,.ion-logo-skype:before,.ion-logo-slack:before,.ion-logo-snapchat:before,.ion-logo-steam:before,.ion-logo-tumblr:before,.ion-logo-tux:before,.ion-logo-twitch:before,.ion-logo-twitter:before,.ion-logo-usd:before,.ion-logo-vimeo:before,.ion-logo-vk:before,.ion-logo-whatsapp:before,.ion-logo-windows:before,.ion-logo-wordpress:before,.ion-logo-xbox:before,.ion-logo-xing:before,.ion-logo-yahoo:before,.ion-logo-yen:before,.ion-logo-youtube:before,.ion-md-add:before,.ion-md-add-circle:before,.ion-md-add-circle-outline:before,.ion-md-airplane:before,.ion-md-alarm:before,.ion-md-albums:before,.ion-md-alert:before,.ion-md-american-football:before,.ion-md-analytics:before,.ion-md-aperture:before,.ion-md-apps:before,.ion-md-appstore:before,.ion-md-archive:before,.ion-md-arrow-back:before,.ion-md-arrow-down:before,.ion-md-arrow-dropdown:before,.ion-md-arrow-dropdown-circle:before,.ion-md-arrow-dropleft:before,.ion-md-arrow-dropleft-circle:before,.ion-md-arrow-dropright:before,.ion-md-arrow-dropright-circle:before,.ion-md-arrow-dropup:before,.ion-md-arrow-dropup-circle:before,.ion-md-arrow-forward:before,.ion-md-arrow-round-back:before,.ion-md-arrow-round-down:before,.ion-md-arrow-round-forward:before,.ion-md-arrow-round-up:before,.ion-md-arrow-up:before,.ion-md-at:before,.ion-md-attach:before,.ion-md-backspace:before,.ion-md-barcode:before,.ion-md-baseball:before,.ion-md-basket:before,.ion-md-basketball:before,.ion-md-battery-charging:before,.ion-md-battery-dead:before,.ion-md-battery-full:before,.ion-md-beaker:before,.ion-md-bed:before,.ion-md-beer:before,.ion-md-bicycle:before,.ion-md-bluetooth:before,.ion-md-boat:before,.ion-md-body:before,.ion-md-bonfire:before,.ion-md-book:before,.ion-md-bookmark:before,.ion-md-bookmarks:before,.ion-md-bowtie:before,.ion-md-briefcase:before,.ion-md-browsers:before,.ion-md-brush:before,.ion-md-bug:before,.ion-md-build:before,.ion-md-bulb:before,.ion-md-bus:before,.ion-md-business:before,.ion-md-cafe:before,.ion-md-calculator:before,.ion-md-calendar:before,.ion-md-call:before,.ion-md-camera:before,.ion-md-car:before,.ion-md-card:before,.ion-md-cart:before,.ion-md-cash:before,.ion-md-cellular:before,.ion-md-chatboxes:before,.ion-md-chatbubbles:before,.ion-md-checkbox:before,.ion-md-checkbox-outline:before,.ion-md-checkmark:before,.ion-md-checkmark-circle:before,.ion-md-checkmark-circle-outline:before,.ion-md-clipboard:before,.ion-md-clock:before,.ion-md-close:before,.ion-md-close-circle:before,.ion-md-close-circle-outline:before,.ion-md-cloud:before,.ion-md-cloud-circle:before,.ion-md-cloud-done:before,.ion-md-cloud-download:before,.ion-md-cloud-outline:before,.ion-md-cloud-upload:before,.ion-md-cloudy:before,.ion-md-cloudy-night:before,.ion-md-code:before,.ion-md-code-download:before,.ion-md-code-working:before,.ion-md-cog:before,.ion-md-color-fill:before,.ion-md-color-filter:before,.ion-md-color-palette:before,.ion-md-color-wand:before,.ion-md-compass:before,.ion-md-construct:before,.ion-md-contact:before,.ion-md-contacts:before,.ion-md-contract:before,.ion-md-contrast:before,.ion-md-copy:before,.ion-md-create:before,.ion-md-crop:before,.ion-md-cube:before,.ion-md-cut:before,.ion-md-desktop:before,.ion-md-disc:before,.ion-md-document:before,.ion-md-done-all:before,.ion-md-download:before,.ion-md-easel:before,.ion-md-egg:before,.ion-md-exit:before,.ion-md-expand:before,.ion-md-eye:before,.ion-md-eye-off:before,.ion-md-fastforward:before,.ion-md-female:before,.ion-md-filing:before,.ion-md-film:before,.ion-md-finger-print:before,.ion-md-fitness:before,.ion-md-flag:before,.ion-md-flame:before,.ion-md-flash:before,.ion-md-flash-off:before,.ion-md-flashlight:before,.ion-md-flask:before,.ion-md-flower:before,.ion-md-folder:before,.ion-md-folder-open:before,.ion-md-football:before,.ion-md-funnel:before,.ion-md-gift:before,.ion-md-git-branch:before,.ion-md-git-commit:before,.ion-md-git-compare:before,.ion-md-git-merge:before,.ion-md-git-network:before,.ion-md-git-pull-request:before,.ion-md-glasses:before,.ion-md-globe:before,.ion-md-grid:before,.ion-md-hammer:before,.ion-md-hand:before,.ion-md-happy:before,.ion-md-headset:before,.ion-md-heart:before,.ion-md-heart-dislike:before,.ion-md-heart-empty:before,.ion-md-heart-half:before,.ion-md-help:before,.ion-md-help-buoy:before,.ion-md-help-circle:before,.ion-md-help-circle-outline:before,.ion-md-home:before,.ion-md-hourglass:before,.ion-md-ice-cream:before,.ion-md-image:before,.ion-md-images:before,.ion-md-infinite:before,.ion-md-information:before,.ion-md-information-circle:before,.ion-md-information-circle-outline:before,.ion-md-jet:before,.ion-md-journal:before,.ion-md-key:before,.ion-md-keypad:before,.ion-md-laptop:before,.ion-md-leaf:before,.ion-md-link:before,.ion-md-list:before,.ion-md-list-box:before,.ion-md-locate:before,.ion-md-lock:before,.ion-md-log-in:before,.ion-md-log-out:before,.ion-md-magnet:before,.ion-md-mail:before,.ion-md-mail-open:before,.ion-md-mail-unread:before,.ion-md-male:before,.ion-md-man:before,.ion-md-map:before,.ion-md-medal:before,.ion-md-medical:before,.ion-md-medkit:before,.ion-md-megaphone:before,.ion-md-menu:before,.ion-md-mic:before,.ion-md-mic-off:before,.ion-md-microphone:before,.ion-md-moon:before,.ion-md-more:before,.ion-md-move:before,.ion-md-musical-note:before,.ion-md-musical-notes:before,.ion-md-navigate:before,.ion-md-notifications:before,.ion-md-notifications-off:before,.ion-md-notifications-outline:before,.ion-md-nuclear:before,.ion-md-nutrition:before,.ion-md-open:before,.ion-md-options:before,.ion-md-outlet:before,.ion-md-paper:before,.ion-md-paper-plane:before,.ion-md-partly-sunny:before,.ion-md-pause:before,.ion-md-paw:before,.ion-md-people:before,.ion-md-person:before,.ion-md-person-add:before,.ion-md-phone-landscape:before,.ion-md-phone-portrait:before,.ion-md-photos:before,.ion-md-pie:before,.ion-md-pin:before,.ion-md-pint:before,.ion-md-pizza:before,.ion-md-planet:before,.ion-md-play:before,.ion-md-play-circle:before,.ion-md-podium:before,.ion-md-power:before,.ion-md-pricetag:before,.ion-md-pricetags:before,.ion-md-print:before,.ion-md-pulse:before,.ion-md-qr-scanner:before,.ion-md-quote:before,.ion-md-radio:before,.ion-md-radio-button-off:before,.ion-md-radio-button-on:before,.ion-md-rainy:before,.ion-md-recording:before,.ion-md-redo:before,.ion-md-refresh:before,.ion-md-refresh-circle:before,.ion-md-remove:before,.ion-md-remove-circle:before,.ion-md-remove-circle-outline:before,.ion-md-reorder:before,.ion-md-repeat:before,.ion-md-resize:before,.ion-md-restaurant:before,.ion-md-return-left:before,.ion-md-return-right:before,.ion-md-reverse-camera:before,.ion-md-rewind:before,.ion-md-ribbon:before,.ion-md-rocket:before,.ion-md-rose:before,.ion-md-sad:before,.ion-md-save:before,.ion-md-school:before,.ion-md-search:before,.ion-md-send:before,.ion-md-settings:before,.ion-md-share:before,.ion-md-share-alt:before,.ion-md-shirt:before,.ion-md-shuffle:before,.ion-md-skip-backward:before,.ion-md-skip-forward:before,.ion-md-snow:before,.ion-md-speedometer:before,.ion-md-square:before,.ion-md-square-outline:before,.ion-md-star:before,.ion-md-star-half:before,.ion-md-star-outline:before,.ion-md-stats:before,.ion-md-stopwatch:before,.ion-md-subway:before,.ion-md-sunny:before,.ion-md-swap:before,.ion-md-switch:before,.ion-md-sync:before,.ion-md-tablet-landscape:before,.ion-md-tablet-portrait:before,.ion-md-tennisball:before,.ion-md-text:before,.ion-md-thermometer:before,.ion-md-thumbs-down:before,.ion-md-thumbs-up:before,.ion-md-thunderstorm:before,.ion-md-time:before,.ion-md-timer:before,.ion-md-today:before,.ion-md-train:before,.ion-md-transgender:before,.ion-md-trash:before,.ion-md-trending-down:before,.ion-md-trending-up:before,.ion-md-trophy:before,.ion-md-tv:before,.ion-md-umbrella:before,.ion-md-undo:before,.ion-md-unlock:before,.ion-md-videocam:before,.ion-md-volume-high:before,.ion-md-volume-low:before,.ion-md-volume-mute:before,.ion-md-volume-off:before,.ion-md-walk:before,.ion-md-wallet:before,.ion-md-warning:before,.ion-md-watch:before,.ion-md-water:before,.ion-md-wifi:before,.ion-md-wine:before,.ion-md-woman:before{display:inline-block;font-family:"Ionicons";speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-ios-add:before{content:""}.ion-ios-add-circle:before{content:""}.ion-ios-add-circle-outline:before{content:""}.ion-ios-airplane:before{content:""}.ion-ios-alarm:before{content:""}.ion-ios-albums:before{content:""}.ion-ios-alert:before{content:""}.ion-ios-american-football:before{content:""}.ion-ios-analytics:before{content:""}.ion-ios-aperture:before{content:""}.ion-ios-apps:before{content:""}.ion-ios-appstore:before{content:""}.ion-ios-archive:before{content:""}.ion-ios-arrow-back:before{content:""}.ion-ios-arrow-down:before{content:""}.ion-ios-arrow-dropdown:before{content:""}.ion-ios-arrow-dropdown-circle:before{content:""}.ion-ios-arrow-dropleft:before{content:""}.ion-ios-arrow-dropleft-circle:before{content:""}.ion-ios-arrow-dropright:before{content:""}.ion-ios-arrow-dropright-circle:before{content:""}.ion-ios-arrow-dropup:before{content:""}.ion-ios-arrow-dropup-circle:before{content:""}.ion-ios-arrow-forward:before{content:""}.ion-ios-arrow-round-back:before{content:""}.ion-ios-arrow-round-down:before{content:""}.ion-ios-arrow-round-forward:before{content:""}.ion-ios-arrow-round-up:before{content:""}.ion-ios-arrow-up:before{content:""}.ion-ios-at:before{content:""}.ion-ios-attach:before{content:""}.ion-ios-backspace:before{content:""}.ion-ios-barcode:before{content:""}.ion-ios-baseball:before{content:""}.ion-ios-basket:before{content:""}.ion-ios-basketball:before{content:""}.ion-ios-battery-charging:before{content:""}.ion-ios-battery-dead:before{content:""}.ion-ios-battery-full:before{content:""}.ion-ios-beaker:before{content:""}.ion-ios-bed:before{content:""}.ion-ios-beer:before{content:""}.ion-ios-bicycle:before{content:""}.ion-ios-bluetooth:before{content:""}.ion-ios-boat:before{content:""}.ion-ios-body:before{content:""}.ion-ios-bonfire:before{content:""}.ion-ios-book:before{content:""}.ion-ios-bookmark:before{content:""}.ion-ios-bookmarks:before{content:""}.ion-ios-bowtie:before{content:""}.ion-ios-briefcase:before{content:""}.ion-ios-browsers:before{content:""}.ion-ios-brush:before{content:""}.ion-ios-bug:before{content:""}.ion-ios-build:before{content:""}.ion-ios-bulb:before{content:""}.ion-ios-bus:before{content:""}.ion-ios-business:before{content:""}.ion-ios-cafe:before{content:""}.ion-ios-calculator:before{content:""}.ion-ios-calendar:before{content:""}.ion-ios-call:before{content:""}.ion-ios-camera:before{content:""}.ion-ios-car:before{content:""}.ion-ios-card:before{content:""}.ion-ios-cart:before{content:""}.ion-ios-cash:before{content:""}.ion-ios-cellular:before{content:""}.ion-ios-chatboxes:before{content:""}.ion-ios-chatbubbles:before{content:""}.ion-ios-checkbox:before{content:""}.ion-ios-checkbox-outline:before{content:""}.ion-ios-checkmark:before{content:""}.ion-ios-checkmark-circle:before{content:""}.ion-ios-checkmark-circle-outline:before{content:""}.ion-ios-clipboard:before{content:""}.ion-ios-clock:before{content:""}.ion-ios-close:before{content:""}.ion-ios-close-circle:before{content:""}.ion-ios-close-circle-outline:before{content:""}.ion-ios-cloud:before{content:""}.ion-ios-cloud-circle:before{content:""}.ion-ios-cloud-done:before{content:""}.ion-ios-cloud-download:before{content:""}.ion-ios-cloud-outline:before{content:""}.ion-ios-cloud-upload:before{content:""}.ion-ios-cloudy:before{content:""}.ion-ios-cloudy-night:before{content:""}.ion-ios-code:before{content:""}.ion-ios-code-download:before{content:""}.ion-ios-code-working:before{content:""}.ion-ios-cog:before{content:""}.ion-ios-color-fill:before{content:""}.ion-ios-color-filter:before{content:""}.ion-ios-color-palette:before{content:""}.ion-ios-color-wand:before{content:""}.ion-ios-compass:before{content:""}.ion-ios-construct:before{content:""}.ion-ios-contact:before{content:""}.ion-ios-contacts:before{content:""}.ion-ios-contract:before{content:""}.ion-ios-contrast:before{content:""}.ion-ios-copy:before{content:""}.ion-ios-create:before{content:""}.ion-ios-crop:before{content:""}.ion-ios-cube:before{content:""}.ion-ios-cut:before{content:""}.ion-ios-desktop:before{content:""}.ion-ios-disc:before{content:""}.ion-ios-document:before{content:""}.ion-ios-done-all:before{content:""}.ion-ios-download:before{content:""}.ion-ios-easel:before{content:""}.ion-ios-egg:before{content:""}.ion-ios-exit:before{content:""}.ion-ios-expand:before{content:""}.ion-ios-eye:before{content:""}.ion-ios-eye-off:before{content:""}.ion-ios-fastforward:before{content:""}.ion-ios-female:before{content:""}.ion-ios-filing:before{content:""}.ion-ios-film:before{content:""}.ion-ios-finger-print:before{content:""}.ion-ios-fitness:before{content:""}.ion-ios-flag:before{content:""}.ion-ios-flame:before{content:""}.ion-ios-flash:before{content:""}.ion-ios-flash-off:before{content:""}.ion-ios-flashlight:before{content:""}.ion-ios-flask:before{content:""}.ion-ios-flower:before{content:""}.ion-ios-folder:before{content:""}.ion-ios-folder-open:before{content:""}.ion-ios-football:before{content:""}.ion-ios-funnel:before{content:""}.ion-ios-gift:before{content:""}.ion-ios-git-branch:before{content:""}.ion-ios-git-commit:before{content:""}.ion-ios-git-compare:before{content:""}.ion-ios-git-merge:before{content:""}.ion-ios-git-network:before{content:""}.ion-ios-git-pull-request:before{content:""}.ion-ios-glasses:before{content:""}.ion-ios-globe:before{content:""}.ion-ios-grid:before{content:""}.ion-ios-hammer:before{content:""}.ion-ios-hand:before{content:""}.ion-ios-happy:before{content:""}.ion-ios-headset:before{content:""}.ion-ios-heart:before{content:""}.ion-ios-heart-dislike:before{content:""}.ion-ios-heart-empty:before{content:""}.ion-ios-heart-half:before{content:""}.ion-ios-help:before{content:""}.ion-ios-help-buoy:before{content:""}.ion-ios-help-circle:before{content:""}.ion-ios-help-circle-outline:before{content:""}.ion-ios-home:before{content:""}.ion-ios-hourglass:before{content:""}.ion-ios-ice-cream:before{content:""}.ion-ios-image:before{content:""}.ion-ios-images:before{content:""}.ion-ios-infinite:before{content:""}.ion-ios-information:before{content:""}.ion-ios-information-circle:before{content:""}.ion-ios-information-circle-outline:before{content:""}.ion-ios-jet:before{content:""}.ion-ios-journal:before{content:""}.ion-ios-key:before{content:""}.ion-ios-keypad:before{content:""}.ion-ios-laptop:before{content:""}.ion-ios-leaf:before{content:""}.ion-ios-link:before{content:""}.ion-ios-list:before{content:""}.ion-ios-list-box:before{content:""}.ion-ios-locate:before{content:""}.ion-ios-lock:before{content:""}.ion-ios-log-in:before{content:""}.ion-ios-log-out:before{content:""}.ion-ios-magnet:before{content:""}.ion-ios-mail:before{content:""}.ion-ios-mail-open:before{content:""}.ion-ios-mail-unread:before{content:""}.ion-ios-male:before{content:""}.ion-ios-man:before{content:""}.ion-ios-map:before{content:""}.ion-ios-medal:before{content:""}.ion-ios-medical:before{content:""}.ion-ios-medkit:before{content:""}.ion-ios-megaphone:before{content:""}.ion-ios-menu:before{content:""}.ion-ios-mic:before{content:""}.ion-ios-mic-off:before{content:""}.ion-ios-microphone:before{content:""}.ion-ios-moon:before{content:""}.ion-ios-more:before{content:""}.ion-ios-move:before{content:""}.ion-ios-musical-note:before{content:""}.ion-ios-musical-notes:before{content:""}.ion-ios-navigate:before{content:""}.ion-ios-notifications:before{content:""}.ion-ios-notifications-off:before{content:""}.ion-ios-notifications-outline:before{content:""}.ion-ios-nuclear:before{content:""}.ion-ios-nutrition:before{content:""}.ion-ios-open:before{content:""}.ion-ios-options:before{content:""}.ion-ios-outlet:before{content:""}.ion-ios-paper:before{content:""}.ion-ios-paper-plane:before{content:""}.ion-ios-partly-sunny:before{content:""}.ion-ios-pause:before{content:""}.ion-ios-paw:before{content:""}.ion-ios-people:before{content:""}.ion-ios-person:before{content:""}.ion-ios-person-add:before{content:""}.ion-ios-phone-landscape:before{content:""}.ion-ios-phone-portrait:before{content:""}.ion-ios-photos:before{content:""}.ion-ios-pie:before{content:""}.ion-ios-pin:before{content:""}.ion-ios-pint:before{content:""}.ion-ios-pizza:before{content:""}.ion-ios-planet:before{content:""}.ion-ios-play:before{content:""}.ion-ios-play-circle:before{content:""}.ion-ios-podium:before{content:""}.ion-ios-power:before{content:""}.ion-ios-pricetag:before{content:""}.ion-ios-pricetags:before{content:""}.ion-ios-print:before{content:""}.ion-ios-pulse:before{content:""}.ion-ios-qr-scanner:before{content:""}.ion-ios-quote:before{content:""}.ion-ios-radio:before{content:""}.ion-ios-radio-button-off:before{content:""}.ion-ios-radio-button-on:before{content:""}.ion-ios-rainy:before{content:""}.ion-ios-recording:before{content:""}.ion-ios-redo:before{content:""}.ion-ios-refresh:before{content:""}.ion-ios-refresh-circle:before{content:""}.ion-ios-remove:before{content:""}.ion-ios-remove-circle:before{content:""}.ion-ios-remove-circle-outline:before{content:""}.ion-ios-reorder:before{content:""}.ion-ios-repeat:before{content:""}.ion-ios-resize:before{content:""}.ion-ios-restaurant:before{content:""}.ion-ios-return-left:before{content:""}.ion-ios-return-right:before{content:""}.ion-ios-reverse-camera:before{content:""}.ion-ios-rewind:before{content:""}.ion-ios-ribbon:before{content:""}.ion-ios-rocket:before{content:""}.ion-ios-rose:before{content:""}.ion-ios-sad:before{content:""}.ion-ios-save:before{content:""}.ion-ios-school:before{content:""}.ion-ios-search:before{content:""}.ion-ios-send:before{content:""}.ion-ios-settings:before{content:""}.ion-ios-share:before{content:""}.ion-ios-share-alt:before{content:""}.ion-ios-shirt:before{content:""}.ion-ios-shuffle:before{content:""}.ion-ios-skip-backward:before{content:""}.ion-ios-skip-forward:before{content:""}.ion-ios-snow:before{content:""}.ion-ios-speedometer:before{content:""}.ion-ios-square:before{content:""}.ion-ios-square-outline:before{content:""}.ion-ios-star:before{content:""}.ion-ios-star-half:before{content:""}.ion-ios-star-outline:before{content:""}.ion-ios-stats:before{content:""}.ion-ios-stopwatch:before{content:""}.ion-ios-subway:before{content:""}.ion-ios-sunny:before{content:""}.ion-ios-swap:before{content:""}.ion-ios-switch:before{content:""}.ion-ios-sync:before{content:""}.ion-ios-tablet-landscape:before{content:""}.ion-ios-tablet-portrait:before{content:""}.ion-ios-tennisball:before{content:""}.ion-ios-text:before{content:""}.ion-ios-thermometer:before{content:""}.ion-ios-thumbs-down:before{content:""}.ion-ios-thumbs-up:before{content:""}.ion-ios-thunderstorm:before{content:""}.ion-ios-time:before{content:""}.ion-ios-timer:before{content:""}.ion-ios-today:before{content:""}.ion-ios-train:before{content:""}.ion-ios-transgender:before{content:""}.ion-ios-trash:before{content:""}.ion-ios-trending-down:before{content:""}.ion-ios-trending-up:before{content:""}.ion-ios-trophy:before{content:""}.ion-ios-tv:before{content:""}.ion-ios-umbrella:before{content:""}.ion-ios-undo:before{content:""}.ion-ios-unlock:before{content:""}.ion-ios-videocam:before{content:""}.ion-ios-volume-high:before{content:""}.ion-ios-volume-low:before{content:""}.ion-ios-volume-mute:before{content:""}.ion-ios-volume-off:before{content:""}.ion-ios-walk:before{content:""}.ion-ios-wallet:before{content:""}.ion-ios-warning:before{content:""}.ion-ios-watch:before{content:""}.ion-ios-water:before{content:""}.ion-ios-wifi:before{content:""}.ion-ios-wine:before{content:""}.ion-ios-woman:before{content:""}.ion-logo-android:before{content:""}.ion-logo-angular:before{content:""}.ion-logo-apple:before{content:""}.ion-logo-bitbucket:before{content:""}.ion-logo-bitcoin:before{content:""}.ion-logo-buffer:before{content:""}.ion-logo-chrome:before{content:""}.ion-logo-closed-captioning:before{content:""}.ion-logo-codepen:before{content:""}.ion-logo-css3:before{content:""}.ion-logo-designernews:before{content:""}.ion-logo-dribbble:before{content:""}.ion-logo-dropbox:before{content:""}.ion-logo-euro:before{content:""}.ion-logo-facebook:before{content:""}.ion-logo-flickr:before{content:""}.ion-logo-foursquare:before{content:""}.ion-logo-freebsd-devil:before{content:""}.ion-logo-game-controller-a:before{content:""}.ion-logo-game-controller-b:before{content:""}.ion-logo-github:before{content:""}.ion-logo-google:before{content:""}.ion-logo-googleplus:before{content:""}.ion-logo-hackernews:before{content:""}.ion-logo-html5:before{content:""}.ion-logo-instagram:before{content:""}.ion-logo-ionic:before{content:""}.ion-logo-ionitron:before{content:""}.ion-logo-javascript:before{content:""}.ion-logo-linkedin:before{content:""}.ion-logo-markdown:before{content:""}.ion-logo-model-s:before{content:""}.ion-logo-no-smoking:before{content:""}.ion-logo-nodejs:before{content:""}.ion-logo-npm:before{content:""}.ion-logo-octocat:before{content:""}.ion-logo-pinterest:before{content:""}.ion-logo-playstation:before{content:""}.ion-logo-polymer:before{content:""}.ion-logo-python:before{content:""}.ion-logo-reddit:before{content:""}.ion-logo-rss:before{content:""}.ion-logo-sass:before{content:""}.ion-logo-skype:before{content:""}.ion-logo-slack:before{content:""}.ion-logo-snapchat:before{content:""}.ion-logo-steam:before{content:""}.ion-logo-tumblr:before{content:""}.ion-logo-tux:before{content:""}.ion-logo-twitch:before{content:""}.ion-logo-twitter:before{content:""}.ion-logo-usd:before{content:""}.ion-logo-vimeo:before{content:""}.ion-logo-vk:before{content:""}.ion-logo-whatsapp:before{content:""}.ion-logo-windows:before{content:""}.ion-logo-wordpress:before{content:""}.ion-logo-xbox:before{content:""}.ion-logo-xing:before{content:""}.ion-logo-yahoo:before{content:""}.ion-logo-yen:before{content:""}.ion-logo-youtube:before{content:""}.ion-md-add:before{content:""}.ion-md-add-circle:before{content:""}.ion-md-add-circle-outline:before{content:""}.ion-md-airplane:before{content:""}.ion-md-alarm:before{content:""}.ion-md-albums:before{content:""}.ion-md-alert:before{content:""}.ion-md-american-football:before{content:""}.ion-md-analytics:before{content:""}.ion-md-aperture:before{content:""}.ion-md-apps:before{content:""}.ion-md-appstore:before{content:""}.ion-md-archive:before{content:""}.ion-md-arrow-back:before{content:""}.ion-md-arrow-down:before{content:""}.ion-md-arrow-dropdown:before{content:""}.ion-md-arrow-dropdown-circle:before{content:""}.ion-md-arrow-dropleft:before{content:""}.ion-md-arrow-dropleft-circle:before{content:""}.ion-md-arrow-dropright:before{content:""}.ion-md-arrow-dropright-circle:before{content:""}.ion-md-arrow-dropup:before{content:""}.ion-md-arrow-dropup-circle:before{content:""}.ion-md-arrow-forward:before{content:""}.ion-md-arrow-round-back:before{content:""}.ion-md-arrow-round-down:before{content:""}.ion-md-arrow-round-forward:before{content:""}.ion-md-arrow-round-up:before{content:""}.ion-md-arrow-up:before{content:""}.ion-md-at:before{content:""}.ion-md-attach:before{content:""}.ion-md-backspace:before{content:""}.ion-md-barcode:before{content:""}.ion-md-baseball:before{content:""}.ion-md-basket:before{content:""}.ion-md-basketball:before{content:""}.ion-md-battery-charging:before{content:""}.ion-md-battery-dead:before{content:""}.ion-md-battery-full:before{content:""}.ion-md-beaker:before{content:""}.ion-md-bed:before{content:""}.ion-md-beer:before{content:""}.ion-md-bicycle:before{content:""}.ion-md-bluetooth:before{content:""}.ion-md-boat:before{content:""}.ion-md-body:before{content:""}.ion-md-bonfire:before{content:""}.ion-md-book:before{content:""}.ion-md-bookmark:before{content:""}.ion-md-bookmarks:before{content:""}.ion-md-bowtie:before{content:""}.ion-md-briefcase:before{content:""}.ion-md-browsers:before{content:""}.ion-md-brush:before{content:""}.ion-md-bug:before{content:""}.ion-md-build:before{content:""}.ion-md-bulb:before{content:""}.ion-md-bus:before{content:""}.ion-md-business:before{content:""}.ion-md-cafe:before{content:""}.ion-md-calculator:before{content:""}.ion-md-calendar:before{content:""}.ion-md-call:before{content:""}.ion-md-camera:before{content:""}.ion-md-car:before{content:""}.ion-md-card:before{content:""}.ion-md-cart:before{content:""}.ion-md-cash:before{content:""}.ion-md-cellular:before{content:""}.ion-md-chatboxes:before{content:""}.ion-md-chatbubbles:before{content:""}.ion-md-checkbox:before{content:""}.ion-md-checkbox-outline:before{content:""}.ion-md-checkmark:before{content:""}.ion-md-checkmark-circle:before{content:""}.ion-md-checkmark-circle-outline:before{content:""}.ion-md-clipboard:before{content:""}.ion-md-clock:before{content:""}.ion-md-close:before{content:""}.ion-md-close-circle:before{content:""}.ion-md-close-circle-outline:before{content:""}.ion-md-cloud:before{content:""}.ion-md-cloud-circle:before{content:""}.ion-md-cloud-done:before{content:""}.ion-md-cloud-download:before{content:""}.ion-md-cloud-outline:before{content:""}.ion-md-cloud-upload:before{content:""}.ion-md-cloudy:before{content:""}.ion-md-cloudy-night:before{content:""}.ion-md-code:before{content:""}.ion-md-code-download:before{content:""}.ion-md-code-working:before{content:""}.ion-md-cog:before{content:""}.ion-md-color-fill:before{content:""}.ion-md-color-filter:before{content:""}.ion-md-color-palette:before{content:""}.ion-md-color-wand:before{content:""}.ion-md-compass:before{content:""}.ion-md-construct:before{content:""}.ion-md-contact:before{content:""}.ion-md-contacts:before{content:""}.ion-md-contract:before{content:""}.ion-md-contrast:before{content:""}.ion-md-copy:before{content:""}.ion-md-create:before{content:""}.ion-md-crop:before{content:""}.ion-md-cube:before{content:""}.ion-md-cut:before{content:""}.ion-md-desktop:before{content:""}.ion-md-disc:before{content:""}.ion-md-document:before{content:""}.ion-md-done-all:before{content:""}.ion-md-download:before{content:""}.ion-md-easel:before{content:""}.ion-md-egg:before{content:""}.ion-md-exit:before{content:""}.ion-md-expand:before{content:""}.ion-md-eye:before{content:""}.ion-md-eye-off:before{content:""}.ion-md-fastforward:before{content:""}.ion-md-female:before{content:""}.ion-md-filing:before{content:""}.ion-md-film:before{content:""}.ion-md-finger-print:before{content:""}.ion-md-fitness:before{content:""}.ion-md-flag:before{content:""}.ion-md-flame:before{content:""}.ion-md-flash:before{content:""}.ion-md-flash-off:before{content:""}.ion-md-flashlight:before{content:""}.ion-md-flask:before{content:""}.ion-md-flower:before{content:""}.ion-md-folder:before{content:""}.ion-md-folder-open:before{content:""}.ion-md-football:before{content:""}.ion-md-funnel:before{content:""}.ion-md-gift:before{content:""}.ion-md-git-branch:before{content:""}.ion-md-git-commit:before{content:""}.ion-md-git-compare:before{content:""}.ion-md-git-merge:before{content:""}.ion-md-git-network:before{content:""}.ion-md-git-pull-request:before{content:""}.ion-md-glasses:before{content:""}.ion-md-globe:before{content:""}.ion-md-grid:before{content:""}.ion-md-hammer:before{content:""}.ion-md-hand:before{content:""}.ion-md-happy:before{content:""}.ion-md-headset:before{content:""}.ion-md-heart:before{content:""}.ion-md-heart-dislike:before{content:""}.ion-md-heart-empty:before{content:""}.ion-md-heart-half:before{content:""}.ion-md-help:before{content:""}.ion-md-help-buoy:before{content:""}.ion-md-help-circle:before{content:""}.ion-md-help-circle-outline:before{content:""}.ion-md-home:before{content:""}.ion-md-hourglass:before{content:""}.ion-md-ice-cream:before{content:""}.ion-md-image:before{content:""}.ion-md-images:before{content:""}.ion-md-infinite:before{content:""}.ion-md-information:before{content:""}.ion-md-information-circle:before{content:""}.ion-md-information-circle-outline:before{content:""}.ion-md-jet:before{content:""}.ion-md-journal:before{content:""}.ion-md-key:before{content:""}.ion-md-keypad:before{content:""}.ion-md-laptop:before{content:""}.ion-md-leaf:before{content:""}.ion-md-link:before{content:""}.ion-md-list:before{content:""}.ion-md-list-box:before{content:""}.ion-md-locate:before{content:""}.ion-md-lock:before{content:""}.ion-md-log-in:before{content:""}.ion-md-log-out:before{content:""}.ion-md-magnet:before{content:""}.ion-md-mail:before{content:""}.ion-md-mail-open:before{content:""}.ion-md-mail-unread:before{content:""}.ion-md-male:before{content:""}.ion-md-man:before{content:""}.ion-md-map:before{content:""}.ion-md-medal:before{content:""}.ion-md-medical:before{content:""}.ion-md-medkit:before{content:""}.ion-md-megaphone:before{content:""}.ion-md-menu:before{content:""}.ion-md-mic:before{content:""}.ion-md-mic-off:before{content:""}.ion-md-microphone:before{content:""}.ion-md-moon:before{content:""}.ion-md-more:before{content:""}.ion-md-move:before{content:""}.ion-md-musical-note:before{content:""}.ion-md-musical-notes:before{content:""}.ion-md-navigate:before{content:""}.ion-md-notifications:before{content:""}.ion-md-notifications-off:before{content:""}.ion-md-notifications-outline:before{content:""}.ion-md-nuclear:before{content:""}.ion-md-nutrition:before{content:""}.ion-md-open:before{content:""}.ion-md-options:before{content:""}.ion-md-outlet:before{content:""}.ion-md-paper:before{content:""}.ion-md-paper-plane:before{content:""}.ion-md-partly-sunny:before{content:""}.ion-md-pause:before{content:""}.ion-md-paw:before{content:""}.ion-md-people:before{content:""}.ion-md-person:before{content:""}.ion-md-person-add:before{content:""}.ion-md-phone-landscape:before{content:""}.ion-md-phone-portrait:before{content:""}.ion-md-photos:before{content:""}.ion-md-pie:before{content:""}.ion-md-pin:before{content:""}.ion-md-pint:before{content:""}.ion-md-pizza:before{content:""}.ion-md-planet:before{content:""}.ion-md-play:before{content:""}.ion-md-play-circle:before{content:""}.ion-md-podium:before{content:""}.ion-md-power:before{content:""}.ion-md-pricetag:before{content:""}.ion-md-pricetags:before{content:""}.ion-md-print:before{content:""}.ion-md-pulse:before{content:""}.ion-md-qr-scanner:before{content:""}.ion-md-quote:before{content:""}.ion-md-radio:before{content:""}.ion-md-radio-button-off:before{content:""}.ion-md-radio-button-on:before{content:""}.ion-md-rainy:before{content:""}.ion-md-recording:before{content:""}.ion-md-redo:before{content:""}.ion-md-refresh:before{content:""}.ion-md-refresh-circle:before{content:""}.ion-md-remove:before{content:""}.ion-md-remove-circle:before{content:""}.ion-md-remove-circle-outline:before{content:""}.ion-md-reorder:before{content:""}.ion-md-repeat:before{content:""}.ion-md-resize:before{content:""}.ion-md-restaurant:before{content:""}.ion-md-return-left:before{content:""}.ion-md-return-right:before{content:""}.ion-md-reverse-camera:before{content:""}.ion-md-rewind:before{content:""}.ion-md-ribbon:before{content:""}.ion-md-rocket:before{content:""}.ion-md-rose:before{content:""}.ion-md-sad:before{content:""}.ion-md-save:before{content:""}.ion-md-school:before{content:""}.ion-md-search:before{content:""}.ion-md-send:before{content:""}.ion-md-settings:before{content:""}.ion-md-share:before{content:""}.ion-md-share-alt:before{content:""}.ion-md-shirt:before{content:""}.ion-md-shuffle:before{content:""}.ion-md-skip-backward:before{content:""}.ion-md-skip-forward:before{content:""}.ion-md-snow:before{content:""}.ion-md-speedometer:before{content:""}.ion-md-square:before{content:""}.ion-md-square-outline:before{content:""}.ion-md-star:before{content:""}.ion-md-star-half:before{content:""}.ion-md-star-outline:before{content:""}.ion-md-stats:before{content:""}.ion-md-stopwatch:before{content:""}.ion-md-subway:before{content:""}.ion-md-sunny:before{content:""}.ion-md-swap:before{content:""}.ion-md-switch:before{content:""}.ion-md-sync:before{content:""}.ion-md-tablet-landscape:before{content:""}.ion-md-tablet-portrait:before{content:""}.ion-md-tennisball:before{content:""}.ion-md-text:before{content:""}.ion-md-thermometer:before{content:""}.ion-md-thumbs-down:before{content:""}.ion-md-thumbs-up:before{content:""}.ion-md-thunderstorm:before{content:""}.ion-md-time:before{content:""}.ion-md-timer:before{content:""}.ion-md-today:before{content:""}.ion-md-train:before{content:""}.ion-md-transgender:before{content:""}.ion-md-trash:before{content:""}.ion-md-trending-down:before{content:""}.ion-md-trending-up:before{content:""}.ion-md-trophy:before{content:""}.ion-md-tv:before{content:""}.ion-md-umbrella:before{content:""}.ion-md-undo:before{content:""}.ion-md-unlock:before{content:""}.ion-md-videocam:before{content:""}.ion-md-volume-high:before{content:""}.ion-md-volume-low:before{content:""}.ion-md-volume-mute:before{content:""}.ion-md-volume-off:before{content:""}.ion-md-walk:before{content:""}.ion-md-wallet:before{content:""}.ion-md-warning:before{content:""}.ion-md-watch:before{content:""}.ion-md-water:before{content:""}.ion-md-wifi:before{content:""}.ion-md-wine:before{content:""}.ion-md-woman:before{content:""} 12 | -------------------------------------------------------------------------------- /css/bootstrap-vue.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * BootstrapVue Custom CSS (https://bootstrap-vue.js.org) 3 | */@media (max-width:575.98px){.bv-d-xs-down-none{display:none!important}}@media (max-width:767.98px){.bv-d-sm-down-none{display:none!important}}@media (max-width:991.98px){.bv-d-md-down-none{display:none!important}}@media (max-width:1199.98px){.bv-d-lg-down-none{display:none!important}}.bv-d-xl-down-none{display:none!important}.card-img-left{border-top-left-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-img-right{border-top-right-radius:calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px)}.dropdown:not(.dropleft) .dropdown-toggle.dropdown-toggle-no-caret::after{display:none!important}.dropdown.dropleft .dropdown-toggle.dropdown-toggle-no-caret::before{display:none!important}.dropdown.b-dropdown .b-dropdown-form{display:inline-block;padding:.25rem 1.5rem;width:100%;clear:both;font-weight:400}.dropdown.b-dropdown .b-dropdown-form:focus{outline:1px dotted!important;outline:5px auto -webkit-focus-ring-color!important}.dropdown.b-dropdown .b-dropdown-form.disabled,.dropdown.b-dropdown .b-dropdown-form:disabled{outline:0!important;color:#6c757d;pointer-events:none}.b-dropdown-text{display:inline-block;padding:.25rem 1.5rem;margin-bottom:0;width:100%;clear:both;font-weight:lighter}.custom-checkbox.b-custom-control-lg,.input-group-lg .custom-checkbox{font-size:1.25rem;line-height:1.5;padding-left:1.875rem}.custom-checkbox.b-custom-control-lg .custom-control-label::before,.input-group-lg .custom-checkbox .custom-control-label::before{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;border-radius:.3rem}.custom-checkbox.b-custom-control-lg .custom-control-label::after,.input-group-lg .custom-checkbox .custom-control-label::after{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;background-size:50% 50%}.custom-checkbox.b-custom-control-sm,.input-group-sm .custom-checkbox{font-size:.875rem;line-height:1.5;padding-left:1.3125rem}.custom-checkbox.b-custom-control-sm .custom-control-label::before,.input-group-sm .custom-checkbox .custom-control-label::before{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;border-radius:.2rem}.custom-checkbox.b-custom-control-sm .custom-control-label::after,.input-group-sm .custom-checkbox .custom-control-label::after{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;background-size:50% 50%}.custom-switch.b-custom-control-lg,.input-group-lg .custom-switch{padding-left:2.8125rem}.custom-switch.b-custom-control-lg .custom-control-label,.input-group-lg .custom-switch .custom-control-label{font-size:1.25rem;line-height:1.5}.custom-switch.b-custom-control-lg .custom-control-label::before,.input-group-lg .custom-switch .custom-control-label::before{top:.3125rem;height:1.25rem;left:-2.8125rem;width:2.1875rem;border-radius:.625rem}.custom-switch.b-custom-control-lg .custom-control-label::after,.input-group-lg .custom-switch .custom-control-label::after{top:calc(.3125rem + 2px);left:calc(-2.8125rem + 2px);width:calc(1.25rem - 4px);height:calc(1.25rem - 4px);border-radius:.625rem;background-size:50% 50%}.custom-switch.b-custom-control-lg .custom-control-input:checked~.custom-control-label::after,.input-group-lg .custom-switch .custom-control-input:checked~.custom-control-label::after{-webkit-transform:translateX(.9375rem);transform:translateX(.9375rem)}.custom-switch.b-custom-control-sm,.input-group-sm .custom-switch{padding-left:1.96875rem}.custom-switch.b-custom-control-sm .custom-control-label,.input-group-sm .custom-switch .custom-control-label{font-size:.875rem;line-height:1.5}.custom-switch.b-custom-control-sm .custom-control-label::before,.input-group-sm .custom-switch .custom-control-label::before{top:.21875rem;left:-1.96875rem;width:1.53125rem;height:.875rem;border-radius:.4375rem}.custom-switch.b-custom-control-sm .custom-control-label::after,.input-group-sm .custom-switch .custom-control-label::after{top:calc(.21875rem + 2px);left:calc(-1.96875rem + 2px);width:calc(.875rem - 4px);height:calc(.875rem - 4px);border-radius:.4375rem;background-size:50% 50%}.custom-switch.b-custom-control-sm .custom-control-input:checked~.custom-control-label::after,.input-group-sm .custom-switch .custom-control-input:checked~.custom-control-label::after{-webkit-transform:translateX(.65625rem);transform:translateX(.65625rem)}.input-group>.input-group-append:last-child>.btn-group:not(:last-child):not(.dropdown-toggle)>.btn,.input-group>.input-group-append:not(:last-child)>.btn-group>.btn,.input-group>.input-group-prepend>.btn-group>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn-group>.btn,.input-group>.input-group-prepend:first-child>.btn-group:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.btn-group>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.b-custom-control-lg .custom-file-input,.b-custom-control-lg .custom-file-label,.b-custom-control-lg.custom-file,.input-group-lg .custom-file-input,.input-group-lg .custom-file-label,.input-group-lg.custom-file{font-size:1.25rem;height:calc(1.5em + 1rem + 2px)}.b-custom-control-lg .custom-file-label,.b-custom-control-lg .custom-file-label:after,.input-group-lg .custom-file-label,.input-group-lg .custom-file-label:after{padding:.5rem 1rem;line-height:1.5}.b-custom-control-lg .custom-file-label,.input-group-lg .custom-file-label{border-radius:.3rem}.b-custom-control-lg .custom-file-label::after,.input-group-lg .custom-file-label::after{font-size:inherit;height:calc(1.5em + 1rem);border-radius:0 .3rem .3rem 0}.b-custom-control-sm .custom-file-input,.b-custom-control-sm .custom-file-label,.b-custom-control-sm.custom-file,.input-group-sm .custom-file-input,.input-group-sm .custom-file-label,.input-group-sm.custom-file{font-size:.875rem;height:calc(1.5em + .5rem + 2px)}.b-custom-control-sm .custom-file-label,.b-custom-control-sm .custom-file-label:after,.input-group-sm .custom-file-label,.input-group-sm .custom-file-label:after{padding:.25rem .5rem;line-height:1.5}.b-custom-control-sm .custom-file-label,.input-group-sm .custom-file-label{border-radius:.2rem}.b-custom-control-sm .custom-file-label::after,.input-group-sm .custom-file-label::after{font-size:inherit;height:calc(1.5em + .5rem);border-radius:0 .2rem .2rem 0}.form-control.is-invalid,.form-control.is-valid,.was-validated .form-control:invalid,.was-validated .form-control:valid{background-position:right calc(.375em + .1875rem) center}input[type=color].form-control{height:calc(1.5em + .75rem + 2px);padding:.125rem .25rem}.input-group-sm input[type=color].form-control,input[type=color].form-control.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.125rem .25rem}.input-group-lg input[type=color].form-control,input[type=color].form-control.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.125rem .25rem}input[type=color].form-control:disabled{background-color:#adb5bd;opacity:.65}.input-group>.custom-range{position:relative;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-range+.custom-file,.input-group>.custom-range+.custom-range,.input-group>.custom-range+.custom-select,.input-group>.custom-range+.form-control,.input-group>.custom-range+.form-control-plaintext{margin-left:-1px}.input-group>.custom-file+.custom-range,.input-group>.custom-range+.custom-range,.input-group>.custom-select+.custom-range,.input-group>.form-control+.custom-range,.input-group>.form-control-plaintext+.custom-range{margin-left:-1px}.input-group>.custom-range:focus{z-index:3}.input-group>.custom-range:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-range:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-range{height:calc(1.5em + .75rem + 2px);padding:0 .75rem;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;height:calc(1.5em + .75rem + 2px);border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.input-group>.custom-range{transition:none}}.input-group>.custom-range:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.input-group>.custom-range:disabled,.input-group>.custom-range[readonly]{background-color:#e9ecef}.input-group-lg>.custom-range{height:calc(1.5em + 1rem + 2px);padding:0 1rem;border-radius:.3rem}.input-group-sm>.custom-range{height:calc(1.5em + .5rem + 2px);padding:0 .5rem;border-radius:.2rem}.input-group .custom-range.is-valid,.was-validated .input-group .custom-range:valid{border-color:#28a745}.input-group .custom-range.is-valid:focus,.was-validated .input-group .custom-range:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-range.is-valid:focus::-webkit-slider-thumb,.was-validated .custom-range:valid:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid:focus::-moz-range-thumb,.was-validated .custom-range:valid:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid:focus::-ms-thumb,.was-validated .custom-range:valid:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #9be7ac}.custom-range.is-valid::-webkit-slider-thumb,.was-validated .custom-range:valid::-webkit-slider-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-webkit-slider-thumb:active,.was-validated .custom-range:valid::-webkit-slider-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-webkit-slider-runnable-track,.was-validated .custom-range:valid::-webkit-slider-runnable-track{background-color:rgba(40,167,69,.35)}.custom-range.is-valid::-moz-range-thumb,.was-validated .custom-range:valid::-moz-range-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-moz-range-thumb:active,.was-validated .custom-range:valid::-moz-range-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-moz-range-track,.was-validated .custom-range:valid::-moz-range-track{background:rgba(40,167,69,.35)}.custom-range.is-valid~.valid-feedback,.custom-range.is-valid~.valid-tooltip,.was-validated .custom-range:valid~.valid-feedback,.was-validated .custom-range:valid~.valid-tooltip{display:block}.custom-range.is-valid::-ms-thumb,.was-validated .custom-range:valid::-ms-thumb{background-color:#28a745;background-image:none}.custom-range.is-valid::-ms-thumb:active,.was-validated .custom-range:valid::-ms-thumb:active{background-color:#9be7ac;background-image:none}.custom-range.is-valid::-ms-track-lower,.was-validated .custom-range:valid::-ms-track-lower{background:rgba(40,167,69,.35)}.custom-range.is-valid::-ms-track-upper,.was-validated .custom-range:valid::-ms-track-upper{background:rgba(40,167,69,.35)}.input-group .custom-range.is-invalid,.was-validated .input-group .custom-range:invalid{border-color:#dc3545}.input-group .custom-range.is-invalid:focus,.was-validated .input-group .custom-range:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-range.is-invalid:focus::-webkit-slider-thumb,.was-validated .custom-range:invalid:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid:focus::-moz-range-thumb,.was-validated .custom-range:invalid:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid:focus::-ms-thumb,.was-validated .custom-range:invalid:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem #f6cdd1}.custom-range.is-invalid::-webkit-slider-thumb,.was-validated .custom-range:invalid::-webkit-slider-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-webkit-slider-thumb:active,.was-validated .custom-range:invalid::-webkit-slider-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-webkit-slider-runnable-track,.was-validated .custom-range:invalid::-webkit-slider-runnable-track{background-color:rgba(220,53,69,.35)}.custom-range.is-invalid::-moz-range-thumb,.was-validated .custom-range:invalid::-moz-range-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-moz-range-thumb:active,.was-validated .custom-range:invalid::-moz-range-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-moz-range-track,.was-validated .custom-range:invalid::-moz-range-track{background:rgba(220,53,69,.35)}.custom-range.is-invalid~.invalid-feedback,.custom-range.is-invalid~.invalid-tooltip,.was-validated .custom-range:invalid~.invalid-feedback,.was-validated .custom-range:invalid~.invalid-tooltip{display:block}.custom-range.is-invalid::-ms-thumb,.was-validated .custom-range:invalid::-ms-thumb{background-color:#dc3545;background-image:none}.custom-range.is-invalid::-ms-thumb:active,.was-validated .custom-range:invalid::-ms-thumb:active{background-color:#f6cdd1;background-image:none}.custom-range.is-invalid::-ms-track-lower,.was-validated .custom-range:invalid::-ms-track-lower{background:rgba(220,53,69,.35)}.custom-range.is-invalid::-ms-track-upper,.was-validated .custom-range:invalid::-ms-track-upper{background:rgba(220,53,69,.35)}.custom-radio.b-custom-control-lg,.input-group-lg .custom-radio{font-size:1.25rem;line-height:1.5;padding-left:1.875rem}.custom-radio.b-custom-control-lg .custom-control-label::before,.input-group-lg .custom-radio .custom-control-label::before{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;border-radius:50%}.custom-radio.b-custom-control-lg .custom-control-label::after,.input-group-lg .custom-radio .custom-control-label::after{top:.3125rem;left:-1.875rem;width:1.25rem;height:1.25rem;background:no-repeat 50%/50% 50%}.custom-radio.b-custom-control-sm,.input-group-sm .custom-radio{font-size:.875rem;line-height:1.5;padding-left:1.3125rem}.custom-radio.b-custom-control-sm .custom-control-label::before,.input-group-sm .custom-radio .custom-control-label::before{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;border-radius:50%}.custom-radio.b-custom-control-sm .custom-control-label::after,.input-group-sm .custom-radio .custom-control-label::after{top:.21875rem;left:-1.3125rem;width:.875rem;height:.875rem;background:no-repeat 50%/50% 50%}.modal-backdrop{opacity:.5}.popover.b-popover{display:block;opacity:1}.popover.b-popover.fade:not(.show){opacity:0}.popover.b-popover.show{opacity:1}.b-popover-primary.popover{background-color:#cce5ff;border-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=top]>.arrow::before,.b-popover-primary.bs-popover-top>.arrow::before{border-top-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=top]>.arrow::after,.b-popover-primary.bs-popover-top>.arrow::after{border-top-color:#cce5ff}.b-popover-primary.bs-popover-auto[x-placement^=right]>.arrow::before,.b-popover-primary.bs-popover-right>.arrow::before{border-right-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=right]>.arrow::after,.b-popover-primary.bs-popover-right>.arrow::after{border-right-color:#cce5ff}.b-popover-primary.bs-popover-auto[x-placement^=bottom]>.arrow::before,.b-popover-primary.bs-popover-bottom>.arrow::before{border-bottom-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=bottom]>.arrow::after,.b-popover-primary.bs-popover-bottom>.arrow::after{border-bottom-color:#bdddff}.b-popover-primary.bs-popover-auto[x-placement^=bottom] .popover-header::before,.b-popover-primary.bs-popover-bottom .popover-header::before{border-bottom-color:#bdddff}.b-popover-primary.bs-popover-auto[x-placement^=left]>.arrow::before,.b-popover-primary.bs-popover-left>.arrow::before{border-left-color:#b8daff}.b-popover-primary.bs-popover-auto[x-placement^=left]>.arrow::after,.b-popover-primary.bs-popover-left>.arrow::after{border-left-color:#cce5ff}.b-popover-primary .popover-header{color:#212529;background-color:#bdddff;border-bottom-color:#a3d0ff}.b-popover-primary .popover-body{color:#004085}.b-popover-secondary.popover{background-color:#e2e3e5;border-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=top]>.arrow::before,.b-popover-secondary.bs-popover-top>.arrow::before{border-top-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=top]>.arrow::after,.b-popover-secondary.bs-popover-top>.arrow::after{border-top-color:#e2e3e5}.b-popover-secondary.bs-popover-auto[x-placement^=right]>.arrow::before,.b-popover-secondary.bs-popover-right>.arrow::before{border-right-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=right]>.arrow::after,.b-popover-secondary.bs-popover-right>.arrow::after{border-right-color:#e2e3e5}.b-popover-secondary.bs-popover-auto[x-placement^=bottom]>.arrow::before,.b-popover-secondary.bs-popover-bottom>.arrow::before{border-bottom-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=bottom]>.arrow::after,.b-popover-secondary.bs-popover-bottom>.arrow::after{border-bottom-color:#dadbde}.b-popover-secondary.bs-popover-auto[x-placement^=bottom] .popover-header::before,.b-popover-secondary.bs-popover-bottom .popover-header::before{border-bottom-color:#dadbde}.b-popover-secondary.bs-popover-auto[x-placement^=left]>.arrow::before,.b-popover-secondary.bs-popover-left>.arrow::before{border-left-color:#d6d8db}.b-popover-secondary.bs-popover-auto[x-placement^=left]>.arrow::after,.b-popover-secondary.bs-popover-left>.arrow::after{border-left-color:#e2e3e5}.b-popover-secondary .popover-header{color:#212529;background-color:#dadbde;border-bottom-color:#ccced2}.b-popover-secondary .popover-body{color:#383d41}.b-popover-success.popover{background-color:#d4edda;border-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=top]>.arrow::before,.b-popover-success.bs-popover-top>.arrow::before{border-top-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=top]>.arrow::after,.b-popover-success.bs-popover-top>.arrow::after{border-top-color:#d4edda}.b-popover-success.bs-popover-auto[x-placement^=right]>.arrow::before,.b-popover-success.bs-popover-right>.arrow::before{border-right-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=right]>.arrow::after,.b-popover-success.bs-popover-right>.arrow::after{border-right-color:#d4edda}.b-popover-success.bs-popover-auto[x-placement^=bottom]>.arrow::before,.b-popover-success.bs-popover-bottom>.arrow::before{border-bottom-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=bottom]>.arrow::after,.b-popover-success.bs-popover-bottom>.arrow::after{border-bottom-color:#c9e8d1}.b-popover-success.bs-popover-auto[x-placement^=bottom] .popover-header::before,.b-popover-success.bs-popover-bottom .popover-header::before{border-bottom-color:#c9e8d1}.b-popover-success.bs-popover-auto[x-placement^=left]>.arrow::before,.b-popover-success.bs-popover-left>.arrow::before{border-left-color:#c3e6cb}.b-popover-success.bs-popover-auto[x-placement^=left]>.arrow::after,.b-popover-success.bs-popover-left>.arrow::after{border-left-color:#d4edda}.b-popover-success .popover-header{color:#212529;background-color:#c9e8d1;border-bottom-color:#b7e1c1}.b-popover-success .popover-body{color:#155724}.b-popover-info.popover{background-color:#d1ecf1;border-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=top]>.arrow::before,.b-popover-info.bs-popover-top>.arrow::before{border-top-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=top]>.arrow::after,.b-popover-info.bs-popover-top>.arrow::after{border-top-color:#d1ecf1}.b-popover-info.bs-popover-auto[x-placement^=right]>.arrow::before,.b-popover-info.bs-popover-right>.arrow::before{border-right-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=right]>.arrow::after,.b-popover-info.bs-popover-right>.arrow::after{border-right-color:#d1ecf1}.b-popover-info.bs-popover-auto[x-placement^=bottom]>.arrow::before,.b-popover-info.bs-popover-bottom>.arrow::before{border-bottom-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=bottom]>.arrow::after,.b-popover-info.bs-popover-bottom>.arrow::after{border-bottom-color:#c5e7ed}.b-popover-info.bs-popover-auto[x-placement^=bottom] .popover-header::before,.b-popover-info.bs-popover-bottom .popover-header::before{border-bottom-color:#c5e7ed}.b-popover-info.bs-popover-auto[x-placement^=left]>.arrow::before,.b-popover-info.bs-popover-left>.arrow::before{border-left-color:#bee5eb}.b-popover-info.bs-popover-auto[x-placement^=left]>.arrow::after,.b-popover-info.bs-popover-left>.arrow::after{border-left-color:#d1ecf1}.b-popover-info .popover-header{color:#212529;background-color:#c5e7ed;border-bottom-color:#b2dfe7}.b-popover-info .popover-body{color:#0c5460}.b-popover-warning.popover{background-color:#fff3cd;border-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=top]>.arrow::before,.b-popover-warning.bs-popover-top>.arrow::before{border-top-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=top]>.arrow::after,.b-popover-warning.bs-popover-top>.arrow::after{border-top-color:#fff3cd}.b-popover-warning.bs-popover-auto[x-placement^=right]>.arrow::before,.b-popover-warning.bs-popover-right>.arrow::before{border-right-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=right]>.arrow::after,.b-popover-warning.bs-popover-right>.arrow::after{border-right-color:#fff3cd}.b-popover-warning.bs-popover-auto[x-placement^=bottom]>.arrow::before,.b-popover-warning.bs-popover-bottom>.arrow::before{border-bottom-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=bottom]>.arrow::after,.b-popover-warning.bs-popover-bottom>.arrow::after{border-bottom-color:#ffefbe}.b-popover-warning.bs-popover-auto[x-placement^=bottom] .popover-header::before,.b-popover-warning.bs-popover-bottom .popover-header::before{border-bottom-color:#ffefbe}.b-popover-warning.bs-popover-auto[x-placement^=left]>.arrow::before,.b-popover-warning.bs-popover-left>.arrow::before{border-left-color:#ffeeba}.b-popover-warning.bs-popover-auto[x-placement^=left]>.arrow::after,.b-popover-warning.bs-popover-left>.arrow::after{border-left-color:#fff3cd}.b-popover-warning .popover-header{color:#212529;background-color:#ffefbe;border-bottom-color:#ffe9a4}.b-popover-warning .popover-body{color:#856404}.b-popover-danger.popover{background-color:#f8d7da;border-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=top]>.arrow::before,.b-popover-danger.bs-popover-top>.arrow::before{border-top-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=top]>.arrow::after,.b-popover-danger.bs-popover-top>.arrow::after{border-top-color:#f8d7da}.b-popover-danger.bs-popover-auto[x-placement^=right]>.arrow::before,.b-popover-danger.bs-popover-right>.arrow::before{border-right-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=right]>.arrow::after,.b-popover-danger.bs-popover-right>.arrow::after{border-right-color:#f8d7da}.b-popover-danger.bs-popover-auto[x-placement^=bottom]>.arrow::before,.b-popover-danger.bs-popover-bottom>.arrow::before{border-bottom-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=bottom]>.arrow::after,.b-popover-danger.bs-popover-bottom>.arrow::after{border-bottom-color:#f6cace}.b-popover-danger.bs-popover-auto[x-placement^=bottom] .popover-header::before,.b-popover-danger.bs-popover-bottom .popover-header::before{border-bottom-color:#f6cace}.b-popover-danger.bs-popover-auto[x-placement^=left]>.arrow::before,.b-popover-danger.bs-popover-left>.arrow::before{border-left-color:#f5c6cb}.b-popover-danger.bs-popover-auto[x-placement^=left]>.arrow::after,.b-popover-danger.bs-popover-left>.arrow::after{border-left-color:#f8d7da}.b-popover-danger .popover-header{color:#212529;background-color:#f6cace;border-bottom-color:#f2b4ba}.b-popover-danger .popover-body{color:#721c24}.b-popover-light.popover{background-color:#fefefe;border-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=top]>.arrow::before,.b-popover-light.bs-popover-top>.arrow::before{border-top-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=top]>.arrow::after,.b-popover-light.bs-popover-top>.arrow::after{border-top-color:#fefefe}.b-popover-light.bs-popover-auto[x-placement^=right]>.arrow::before,.b-popover-light.bs-popover-right>.arrow::before{border-right-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=right]>.arrow::after,.b-popover-light.bs-popover-right>.arrow::after{border-right-color:#fefefe}.b-popover-light.bs-popover-auto[x-placement^=bottom]>.arrow::before,.b-popover-light.bs-popover-bottom>.arrow::before{border-bottom-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=bottom]>.arrow::after,.b-popover-light.bs-popover-bottom>.arrow::after{border-bottom-color:#f6f6f6}.b-popover-light.bs-popover-auto[x-placement^=bottom] .popover-header::before,.b-popover-light.bs-popover-bottom .popover-header::before{border-bottom-color:#f6f6f6}.b-popover-light.bs-popover-auto[x-placement^=left]>.arrow::before,.b-popover-light.bs-popover-left>.arrow::before{border-left-color:#fdfdfe}.b-popover-light.bs-popover-auto[x-placement^=left]>.arrow::after,.b-popover-light.bs-popover-left>.arrow::after{border-left-color:#fefefe}.b-popover-light .popover-header{color:#212529;background-color:#f6f6f6;border-bottom-color:#eaeaea}.b-popover-light .popover-body{color:#818182}.b-popover-dark.popover{background-color:#d6d8d9;border-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=top]>.arrow::before,.b-popover-dark.bs-popover-top>.arrow::before{border-top-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=top]>.arrow::after,.b-popover-dark.bs-popover-top>.arrow::after{border-top-color:#d6d8d9}.b-popover-dark.bs-popover-auto[x-placement^=right]>.arrow::before,.b-popover-dark.bs-popover-right>.arrow::before{border-right-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=right]>.arrow::after,.b-popover-dark.bs-popover-right>.arrow::after{border-right-color:#d6d8d9}.b-popover-dark.bs-popover-auto[x-placement^=bottom]>.arrow::before,.b-popover-dark.bs-popover-bottom>.arrow::before{border-bottom-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=bottom]>.arrow::after,.b-popover-dark.bs-popover-bottom>.arrow::after{border-bottom-color:#ced0d2}.b-popover-dark.bs-popover-auto[x-placement^=bottom] .popover-header::before,.b-popover-dark.bs-popover-bottom .popover-header::before{border-bottom-color:#ced0d2}.b-popover-dark.bs-popover-auto[x-placement^=left]>.arrow::before,.b-popover-dark.bs-popover-left>.arrow::before{border-left-color:#c6c8ca}.b-popover-dark.bs-popover-auto[x-placement^=left]>.arrow::after,.b-popover-dark.bs-popover-left>.arrow::after{border-left-color:#d6d8d9}.b-popover-dark .popover-header{color:#212529;background-color:#ced0d2;border-bottom-color:#c1c4c5}.b-popover-dark .popover-body{color:#1b1e21}.table.b-table.b-table-fixed{table-layout:fixed}.table.b-table.b-table-no-border-collapse{border-collapse:separate;border-spacing:0}.table.b-table[aria-busy=true]{opacity:.55}.table.b-table>tbody>tr.b-table-details>td{border-top:none!important}.table.b-table>caption{caption-side:bottom}.table.b-table.b-table-caption-top>caption{caption-side:top!important}.table.b-table>tbody>.table-active,.table.b-table>tbody>.table-active>td,.table.b-table>tbody>.table-active>th{background-color:rgba(0,0,0,.075)}.table.b-table.table-hover>tbody>tr.table-active:hover td,.table.b-table.table-hover>tbody>tr.table-active:hover th{color:#212529;background-image:linear-gradient(rgba(0,0,0,.075),rgba(0,0,0,.075));background-repeat:no-repeat}.table.b-table>tbody>.bg-active,.table.b-table>tbody>.bg-active>td,.table.b-table>tbody>.bg-active>th{background-color:rgba(255,255,255,.075)!important}.table.b-table.table-hover.table-dark>tbody>tr.bg-active:hover td,.table.b-table.table-hover.table-dark>tbody>tr.bg-active:hover th{color:#fff;background-image:linear-gradient(rgba(255,255,255,.075),rgba(255,255,255,.075));background-repeat:no-repeat}.b-table-sticky-header,.table-responsive,[class*=table-responsive-]{margin-bottom:1rem}.b-table-sticky-header>.table,.table-responsive>.table,[class*=table-responsive-]>.table{margin-bottom:0}.b-table-sticky-header{overflow-y:auto;max-height:300px}@supports ((position:-webkit-sticky) or (position:sticky)){.b-table-sticky-header>.table.b-table>thead>tr>th{position:-webkit-sticky;position:sticky;top:0;z-index:2}.b-table-sticky-header>.table.b-table>tbody>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>tfoot>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>thead>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tbody>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tfoot>tr>.b-table-sticky-column,.table-responsive>.table.b-table>thead>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tbody>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tfoot>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>thead>tr>.b-table-sticky-column{position:-webkit-sticky;position:sticky;left:0}.b-table-sticky-header>.table.b-table>thead>tr>.b-table-sticky-column,.table-responsive>.table.b-table>thead>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>thead>tr>.b-table-sticky-column{z-index:5}.b-table-sticky-header>.table.b-table>tbody>tr>.b-table-sticky-column,.b-table-sticky-header>.table.b-table>tfoot>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tbody>tr>.b-table-sticky-column,.table-responsive>.table.b-table>tfoot>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tbody>tr>.b-table-sticky-column,[class*=table-responsive-]>.table.b-table>tfoot>tr>.b-table-sticky-column{z-index:2}.table.b-table>tbody>tr>.table-b-table-default,.table.b-table>tfoot>tr>.table-b-table-default,.table.b-table>thead>tr>.table-b-table-default{color:#212529;background-color:#fff}.table.b-table.table-dark>tbody>tr>.bg-b-table-default,.table.b-table.table-dark>tfoot>tr>.bg-b-table-default,.table.b-table.table-dark>thead>tr>.bg-b-table-default{color:#fff;background-color:#343a40}.table.b-table.table-striped>tbody>tr:nth-of-type(odd)>.table-b-table-default{background-image:linear-gradient(rgba(0,0,0,.05),rgba(0,0,0,.05));background-repeat:no-repeat}.table.b-table.table-striped.table-dark>tbody>tr:nth-of-type(odd)>.bg-b-table-default{background-image:linear-gradient(rgba(255,255,255,.05),rgba(255,255,255,.05));background-repeat:no-repeat}.table.b-table.table-hover>tbody>tr:hover>.table-b-table-default{color:#212529;background-image:linear-gradient(rgba(0,0,0,.075),rgba(0,0,0,.075));background-repeat:no-repeat}.table.b-table.table-hover.table-dark>tbody>tr:hover>.bg-b-table-default{color:#fff;background-image:linear-gradient(rgba(255,255,255,.075),rgba(255,255,255,.075));background-repeat:no-repeat}}.table.b-table>tfoot>tr>[aria-sort],.table.b-table>thead>tr>[aria-sort]{cursor:pointer;background-image:none;background-repeat:no-repeat;background-size:.65em 1em}.table.b-table>tfoot>tr>[aria-sort]:not(.b-table-sort-icon-left),.table.b-table>thead>tr>[aria-sort]:not(.b-table-sort-icon-left){background-position:right calc(.75rem / 2) center;padding-right:calc(.75rem + .65em)}.table.b-table>tfoot>tr>[aria-sort].b-table-sort-icon-left,.table.b-table>thead>tr>[aria-sort].b-table-sort-icon-left{background-position:left calc(.75rem / 2) center;padding-left:calc(.75rem + .65em)}.table.b-table>tfoot>tr>[aria-sort=none],.table.b-table>thead>tr>[aria-sort=none]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='black' opacity='.3' d='M51 1l25 23 24 22H1l25-22zM51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table>tfoot>tr>[aria-sort=ascending],.table.b-table>thead>tr>[aria-sort=ascending]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='black' d='M51 1l25 23 24 22H1l25-22z'/%3e%3cpath fill='black' opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table>tfoot>tr>[aria-sort=descending],.table.b-table>thead>tr>[aria-sort=descending]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='black' opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3e%3cpath fill='black' d='M51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table.table-dark>tfoot>tr>[aria-sort=none],.table.b-table.table-dark>thead>tr>[aria-sort=none],.table.b-table>.thead-dark>tr>[aria-sort=none]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='white' opacity='.3' d='M51 1l25 23 24 22H1l25-22zM51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table.table-dark>tfoot>tr>[aria-sort=ascending],.table.b-table.table-dark>thead>tr>[aria-sort=ascending],.table.b-table>.thead-dark>tr>[aria-sort=ascending]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='white' d='M51 1l25 23 24 22H1l25-22z'/%3e%3cpath fill='white' opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table.table-dark>tfoot>tr>[aria-sort=descending],.table.b-table.table-dark>thead>tr>[aria-sort=descending],.table.b-table>.thead-dark>tr>[aria-sort=descending]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='white' opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3e%3cpath fill='white' d='M51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table>tfoot>tr>.table-dark[aria-sort=none],.table.b-table>thead>tr>.table-dark[aria-sort=none]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='white' opacity='.3' d='M51 1l25 23 24 22H1l25-22zM51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table>tfoot>tr>.table-dark[aria-sort=ascending],.table.b-table>thead>tr>.table-dark[aria-sort=ascending]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='white' d='M51 1l25 23 24 22H1l25-22z'/%3e%3cpath fill='white' opacity='.3' d='M51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table>tfoot>tr>.table-dark[aria-sort=descending],.table.b-table>thead>tr>.table-dark[aria-sort=descending]{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='101' height='101' view-box='0 0 101 101' preserveAspectRatio='none'%3e%3cpath fill='white' opacity='.3' d='M51 1l25 23 24 22H1l25-22z'/%3e%3cpath fill='white' d='M51 101l25-23 24-22H1l25 22z'/%3e%3c/svg%3e")}.table.b-table.table-sm>tfoot>tr>[aria-sort]:not(.b-table-sort-icon-left),.table.b-table.table-sm>thead>tr>[aria-sort]:not(.b-table-sort-icon-left){background-position:right calc(.3rem / 2) center;padding-right:calc(.3rem + .65em)}.table.b-table.table-sm>tfoot>tr>[aria-sort].b-table-sort-icon-left,.table.b-table.table-sm>thead>tr>[aria-sort].b-table-sort-icon-left{background-position:left calc(.3rem / 2) center;padding-left:calc(.3rem + .65em)}.table.b-table.b-table-selectable>tbody>tr{cursor:pointer}.table.b-table.b-table-selectable.b-table-selecting.b-table-select-range>tbody>tr{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media (max-width:575.98px){.table.b-table.b-table-stacked-sm{display:block;width:100%}.table.b-table.b-table-stacked-sm>caption,.table.b-table.b-table-stacked-sm>tbody,.table.b-table.b-table-stacked-sm>tbody>tr,.table.b-table.b-table-stacked-sm>tbody>tr>td,.table.b-table.b-table-stacked-sm>tbody>tr>th{display:block}.table.b-table.b-table-stacked-sm>tfoot,.table.b-table.b-table-stacked-sm>thead{display:none}.table.b-table.b-table-stacked-sm>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-sm>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-sm>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-sm>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-sm>caption{caption-side:top!important}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]::before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 calc(1rem / 2) 0 0;margin:0}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]::after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-sm>tbody>tr>[data-label]>div{display:inline-block;width:calc(100% - 40%);padding:0 0 0 calc(1rem / 2);margin:0}.table.b-table.b-table-stacked-sm>tbody>tr.bottom-row,.table.b-table.b-table-stacked-sm>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-sm>tbody>tr>:first-child{border-top-width:3px}.table.b-table.b-table-stacked-sm>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-sm>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:767.98px){.table.b-table.b-table-stacked-md{display:block;width:100%}.table.b-table.b-table-stacked-md>caption,.table.b-table.b-table-stacked-md>tbody,.table.b-table.b-table-stacked-md>tbody>tr,.table.b-table.b-table-stacked-md>tbody>tr>td,.table.b-table.b-table-stacked-md>tbody>tr>th{display:block}.table.b-table.b-table-stacked-md>tfoot,.table.b-table.b-table-stacked-md>thead{display:none}.table.b-table.b-table-stacked-md>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-md>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-md>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-md>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-md>caption{caption-side:top!important}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]::before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 calc(1rem / 2) 0 0;margin:0}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]::after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-md>tbody>tr>[data-label]>div{display:inline-block;width:calc(100% - 40%);padding:0 0 0 calc(1rem / 2);margin:0}.table.b-table.b-table-stacked-md>tbody>tr.bottom-row,.table.b-table.b-table-stacked-md>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-md>tbody>tr>:first-child{border-top-width:3px}.table.b-table.b-table-stacked-md>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-md>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:991.98px){.table.b-table.b-table-stacked-lg{display:block;width:100%}.table.b-table.b-table-stacked-lg>caption,.table.b-table.b-table-stacked-lg>tbody,.table.b-table.b-table-stacked-lg>tbody>tr,.table.b-table.b-table-stacked-lg>tbody>tr>td,.table.b-table.b-table-stacked-lg>tbody>tr>th{display:block}.table.b-table.b-table-stacked-lg>tfoot,.table.b-table.b-table-stacked-lg>thead{display:none}.table.b-table.b-table-stacked-lg>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-lg>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-lg>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-lg>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-lg>caption{caption-side:top!important}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]::before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 calc(1rem / 2) 0 0;margin:0}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]::after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-lg>tbody>tr>[data-label]>div{display:inline-block;width:calc(100% - 40%);padding:0 0 0 calc(1rem / 2);margin:0}.table.b-table.b-table-stacked-lg>tbody>tr.bottom-row,.table.b-table.b-table-stacked-lg>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-lg>tbody>tr>:first-child{border-top-width:3px}.table.b-table.b-table-stacked-lg>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-lg>tbody>tr>[rowspan]+th{border-top-width:3px}}@media (max-width:1199.98px){.table.b-table.b-table-stacked-xl{display:block;width:100%}.table.b-table.b-table-stacked-xl>caption,.table.b-table.b-table-stacked-xl>tbody,.table.b-table.b-table-stacked-xl>tbody>tr,.table.b-table.b-table-stacked-xl>tbody>tr>td,.table.b-table.b-table-stacked-xl>tbody>tr>th{display:block}.table.b-table.b-table-stacked-xl>tfoot,.table.b-table.b-table-stacked-xl>thead{display:none}.table.b-table.b-table-stacked-xl>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked-xl>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked-xl>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked-xl>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked-xl>caption{caption-side:top!important}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]::before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 calc(1rem / 2) 0 0;margin:0}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]::after{display:block;clear:both;content:""}.table.b-table.b-table-stacked-xl>tbody>tr>[data-label]>div{display:inline-block;width:calc(100% - 40%);padding:0 0 0 calc(1rem / 2);margin:0}.table.b-table.b-table-stacked-xl>tbody>tr.bottom-row,.table.b-table.b-table-stacked-xl>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked-xl>tbody>tr>:first-child{border-top-width:3px}.table.b-table.b-table-stacked-xl>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked-xl>tbody>tr>[rowspan]+th{border-top-width:3px}}.table.b-table.b-table-stacked{display:block;width:100%}.table.b-table.b-table-stacked>caption,.table.b-table.b-table-stacked>tbody,.table.b-table.b-table-stacked>tbody>tr,.table.b-table.b-table-stacked>tbody>tr>td,.table.b-table.b-table-stacked>tbody>tr>th{display:block}.table.b-table.b-table-stacked>tfoot,.table.b-table.b-table-stacked>thead{display:none}.table.b-table.b-table-stacked>tfoot>tr.b-table-bottom-row,.table.b-table.b-table-stacked>tfoot>tr.b-table-top-row,.table.b-table.b-table-stacked>thead>tr.b-table-bottom-row,.table.b-table.b-table-stacked>thead>tr.b-table-top-row{display:none}.table.b-table.b-table-stacked>caption{caption-side:top!important}.table.b-table.b-table-stacked>tbody>tr>[data-label]::before{content:attr(data-label);width:40%;float:left;text-align:right;overflow-wrap:break-word;font-weight:700;font-style:normal;padding:0 calc(1rem / 2) 0 0;margin:0}.table.b-table.b-table-stacked>tbody>tr>[data-label]::after{display:block;clear:both;content:""}.table.b-table.b-table-stacked>tbody>tr>[data-label]>div{display:inline-block;width:calc(100% - 40%);padding:0 0 0 calc(1rem / 2);margin:0}.table.b-table.b-table-stacked>tbody>tr.bottom-row,.table.b-table.b-table-stacked>tbody>tr.top-row{display:none}.table.b-table.b-table-stacked>tbody>tr>:first-child{border-top-width:3px}.table.b-table.b-table-stacked>tbody>tr>[rowspan]+td,.table.b-table.b-table-stacked>tbody>tr>[rowspan]+th{border-top-width:3px}.b-toast{display:block;position:relative;max-width:350px;-webkit-backface-visibility:hidden;backface-visibility:hidden;background-clip:padding-box;z-index:1;border-radius:.25rem}.b-toast .toast{background-color:rgba(255,255,255,.85)}.b-toast:not(:last-child){margin-bottom:.75rem}.b-toast.b-toast-solid .toast{background-color:#fff}.b-toast .toast{opacity:1}.b-toast .toast.fade:not(.show){opacity:0}.b-toast .toast .toast-body{display:block}.b-toast-primary .toast{background-color:rgba(230,242,255,.85);border-color:rgba(184,218,255,.85);color:#004085}.b-toast-primary .toast .toast-header{color:#004085;background-color:rgba(204,229,255,.85);border-bottom-color:rgba(184,218,255,.85)}.b-toast-primary.b-toast-solid .toast{background-color:#e6f2ff}.b-toast-secondary .toast{background-color:rgba(239,240,241,.85);border-color:rgba(214,216,219,.85);color:#383d41}.b-toast-secondary .toast .toast-header{color:#383d41;background-color:rgba(226,227,229,.85);border-bottom-color:rgba(214,216,219,.85)}.b-toast-secondary.b-toast-solid .toast{background-color:#eff0f1}.b-toast-success .toast{background-color:rgba(230,245,233,.85);border-color:rgba(195,230,203,.85);color:#155724}.b-toast-success .toast .toast-header{color:#155724;background-color:rgba(212,237,218,.85);border-bottom-color:rgba(195,230,203,.85)}.b-toast-success.b-toast-solid .toast{background-color:#e6f5e9}.b-toast-info .toast{background-color:rgba(229,244,247,.85);border-color:rgba(190,229,235,.85);color:#0c5460}.b-toast-info .toast .toast-header{color:#0c5460;background-color:rgba(209,236,241,.85);border-bottom-color:rgba(190,229,235,.85)}.b-toast-info.b-toast-solid .toast{background-color:#e5f4f7}.b-toast-warning .toast{background-color:rgba(255,249,231,.85);border-color:rgba(255,238,186,.85);color:#856404}.b-toast-warning .toast .toast-header{color:#856404;background-color:rgba(255,243,205,.85);border-bottom-color:rgba(255,238,186,.85)}.b-toast-warning.b-toast-solid .toast{background-color:#fff9e7}.b-toast-danger .toast{background-color:rgba(252,237,238,.85);border-color:rgba(245,198,203,.85);color:#721c24}.b-toast-danger .toast .toast-header{color:#721c24;background-color:rgba(248,215,218,.85);border-bottom-color:rgba(245,198,203,.85)}.b-toast-danger.b-toast-solid .toast{background-color:#fcedee}.b-toast-light .toast{background-color:rgba(255,255,255,.85);border-color:rgba(253,253,254,.85);color:#818182}.b-toast-light .toast .toast-header{color:#818182;background-color:rgba(254,254,254,.85);border-bottom-color:rgba(253,253,254,.85)}.b-toast-light.b-toast-solid .toast{background-color:#fff}.b-toast-dark .toast{background-color:rgba(227,229,229,.85);border-color:rgba(198,200,202,.85);color:#1b1e21}.b-toast-dark .toast .toast-header{color:#1b1e21;background-color:rgba(214,216,217,.85);border-bottom-color:rgba(198,200,202,.85)}.b-toast-dark.b-toast-solid .toast{background-color:#e3e5e5}.b-toaster{z-index:1100}.b-toaster .b-toaster-slot{position:relative;display:block}.b-toaster .b-toaster-slot:empty{display:none!important}.b-toaster.b-toaster-bottom-center,.b-toaster.b-toaster-bottom-full,.b-toaster.b-toaster-bottom-left,.b-toaster.b-toaster-bottom-right,.b-toaster.b-toaster-top-center,.b-toaster.b-toaster-top-full,.b-toaster.b-toaster-top-left,.b-toaster.b-toaster-top-right{position:fixed;left:.5rem;right:.5rem;margin:0;padding:0;height:0;overflow:visible}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{position:absolute;max-width:350px;width:100%;left:0;right:0;padding:0;margin:0}.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot{width:100%;max-width:100%}.b-toaster.b-toaster-bottom-full .b-toaster-slot .b-toast,.b-toaster.b-toaster-bottom-full .b-toaster-slot .toast,.b-toaster.b-toaster-top-full .b-toaster-slot .b-toast,.b-toaster.b-toaster-top-full .b-toaster-slot .toast{width:100%;max-width:100%}.b-toaster.b-toaster-top-center,.b-toaster.b-toaster-top-full,.b-toaster.b-toaster-top-left,.b-toaster.b-toaster-top-right{top:0}.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-full .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{top:.5rem}.b-toaster.b-toaster-bottom-center,.b-toaster.b-toaster-bottom-full,.b-toaster.b-toaster-bottom-left,.b-toaster.b-toaster-bottom-right{bottom:0}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-full .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot{bottom:.5rem}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-right .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-right .b-toaster-slot{margin-left:auto}.b-toaster.b-toaster-bottom-center .b-toaster-slot,.b-toaster.b-toaster-bottom-left .b-toaster-slot,.b-toaster.b-toaster-top-center .b-toaster-slot,.b-toaster.b-toaster-top-left .b-toaster-slot{margin-right:auto}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-move,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-move,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-move,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-move{transition:-webkit-transform 175ms;transition:transform 175ms;transition:transform 175ms,-webkit-transform 175ms}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-enter-to .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-active .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-enter-to .toast.fade{transition-delay:175ms}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active{position:absolute;transition-delay:175ms}.b-toaster.b-toaster-bottom-left .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-bottom-right .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-top-left .b-toast.b-toaster-leave-active .toast.fade,.b-toaster.b-toaster-top-right .b-toast.b-toaster-leave-active .toast.fade{transition-delay:0s}.tooltip.b-tooltip{display:block;opacity:.9}.tooltip.b-tooltip.fade:not(.show){opacity:0}.tooltip.b-tooltip.show{opacity:.9}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.b-tooltip-primary.bs-tooltip-top .arrow::before{border-top-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.b-tooltip-primary.bs-tooltip-right .arrow::before{border-right-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.b-tooltip-primary.bs-tooltip-bottom .arrow::before{border-bottom-color:#007bff}.tooltip.b-tooltip-primary.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.b-tooltip-primary.bs-tooltip-left .arrow::before{border-left-color:#007bff}.tooltip.b-tooltip-primary .tooltip-inner{color:#fff;background-color:#007bff}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.b-tooltip-secondary.bs-tooltip-top .arrow::before{border-top-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.b-tooltip-secondary.bs-tooltip-right .arrow::before{border-right-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.b-tooltip-secondary.bs-tooltip-bottom .arrow::before{border-bottom-color:#6c757d}.tooltip.b-tooltip-secondary.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.b-tooltip-secondary.bs-tooltip-left .arrow::before{border-left-color:#6c757d}.tooltip.b-tooltip-secondary .tooltip-inner{color:#fff;background-color:#6c757d}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.b-tooltip-success.bs-tooltip-top .arrow::before{border-top-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.b-tooltip-success.bs-tooltip-right .arrow::before{border-right-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.b-tooltip-success.bs-tooltip-bottom .arrow::before{border-bottom-color:#28a745}.tooltip.b-tooltip-success.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.b-tooltip-success.bs-tooltip-left .arrow::before{border-left-color:#28a745}.tooltip.b-tooltip-success .tooltip-inner{color:#fff;background-color:#28a745}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.b-tooltip-info.bs-tooltip-top .arrow::before{border-top-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.b-tooltip-info.bs-tooltip-right .arrow::before{border-right-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.b-tooltip-info.bs-tooltip-bottom .arrow::before{border-bottom-color:#17a2b8}.tooltip.b-tooltip-info.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.b-tooltip-info.bs-tooltip-left .arrow::before{border-left-color:#17a2b8}.tooltip.b-tooltip-info .tooltip-inner{color:#fff;background-color:#17a2b8}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.b-tooltip-warning.bs-tooltip-top .arrow::before{border-top-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.b-tooltip-warning.bs-tooltip-right .arrow::before{border-right-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.b-tooltip-warning.bs-tooltip-bottom .arrow::before{border-bottom-color:#ffc107}.tooltip.b-tooltip-warning.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.b-tooltip-warning.bs-tooltip-left .arrow::before{border-left-color:#ffc107}.tooltip.b-tooltip-warning .tooltip-inner{color:#212529;background-color:#ffc107}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.b-tooltip-danger.bs-tooltip-top .arrow::before{border-top-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.b-tooltip-danger.bs-tooltip-right .arrow::before{border-right-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.b-tooltip-danger.bs-tooltip-bottom .arrow::before{border-bottom-color:#dc3545}.tooltip.b-tooltip-danger.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.b-tooltip-danger.bs-tooltip-left .arrow::before{border-left-color:#dc3545}.tooltip.b-tooltip-danger .tooltip-inner{color:#fff;background-color:#dc3545}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.b-tooltip-light.bs-tooltip-top .arrow::before{border-top-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.b-tooltip-light.bs-tooltip-right .arrow::before{border-right-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.b-tooltip-light.bs-tooltip-bottom .arrow::before{border-bottom-color:#f8f9fa}.tooltip.b-tooltip-light.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.b-tooltip-light.bs-tooltip-left .arrow::before{border-left-color:#f8f9fa}.tooltip.b-tooltip-light .tooltip-inner{color:#212529;background-color:#f8f9fa}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.b-tooltip-dark.bs-tooltip-top .arrow::before{border-top-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.b-tooltip-dark.bs-tooltip-right .arrow::before{border-right-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.b-tooltip-dark.bs-tooltip-bottom .arrow::before{border-bottom-color:#343a40}.tooltip.b-tooltip-dark.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.b-tooltip-dark.bs-tooltip-left .arrow::before{border-left-color:#343a40}.tooltip.b-tooltip-dark .tooltip-inner{color:#fff;background-color:#343a40} 4 | /*# sourceMappingURL=bootstrap-vue.min.css.map */ --------------------------------------------------------------------------------