diff --git a/.esformatter b/.esformatter new file mode 100644 index 000000000..a53a9ecb8 --- /dev/null +++ b/.esformatter @@ -0,0 +1,33 @@ +{ + "plugins": [ + "esformatter-quotes", + "esformatter-braces", + "esformatter-semicolons" + ], + "quotes": { + "type": "single", + "avoidEscape": false + }, + "whiteSpace": { + "before": { + "ParameterList": -1, + "ParameterComma": -1, + "FunctionDeclarationOpeningBrace": -1, + "FunctionDeclarationClosingBrace": -1, + "ForStatementExpressionOpening": -1 + }, + "after": { + "FunctionName": -1, + "ParameterComma": 1, + "FunctionReservedWord": -1, + "ParameterList": -1, + "FunctionDeclarationOpeningBrace": -1, + "PropertyName": -1 + } + }, + "lineBreak": { + "before": { + "EndOfFile": 1 + } + } +} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..4bd74472e --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,24 @@ +{ + "env": { + "browser": false, + "commonjs": true, + "es6": true, + "node": true + }, + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "sourceType": "module" + }, + "rules": { + "semi": "error", + "eqeqeq": "error", + "no-const-assign": "warn", + "no-this-before-super": "warn", + "no-unreachable": "warn", + "no-unused-vars": "warn", + "constructor-super": "warn", + "valid-typeof": "warn" + } +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..7019aee90 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "jshint.enable": false +} \ No newline at end of file diff --git a/Data/appConfig.json b/Data/appConfig.json new file mode 100644 index 000000000..8b900856e --- /dev/null +++ b/Data/appConfig.json @@ -0,0 +1,106 @@ +{ + "broadcast": { + "msgId": "7lswwqfVCjHA", + "message": "A critical SmartApp update was just published for NST Manager. Please update your NST Manager SmartApps and Devices to avoid any disruptions", + "type": "warn", + "minVer": "5.5.2", + "devBannerMsg": { + "msgId": "", + "message": "", + "type": "warn", + "minVer": "5.5.2", + "expireDt": "Wed Feb 20 00:00:00 EST 2018" + } + }, + "updater": { + "updateVer": 1, + "updateMsg": "", + "updateDesc": "", + "updateType": "std", + "setupVersion": 2, + "versions": { + "app": { + "ver": "5.6.4" + }, + "autoapp": { + "ver": "5.5.0" + }, + "thermostat": { + "ver": "5.4.6" + }, + "protect": { + "ver": "5.4.3" + }, + "camera": { + "ver": "5.4.5" + }, + "presence": { + "ver": "5.4.4" + }, + "weather": { + "ver": "5.5.2" + }, + "stream": { + "ver": "2.0.1" + } + } + }, + "settings": { + "askAlexa": { + "enAaMsgQueue": true, + "enMultiQueue": false + }, + "database": { + "disableExceptions": true, + "sendExceptions": false, + "exceptionKey": "exceptions", + "pullSettingFromFB": false, + "metricsUrl": "https://nst-manager-metrics.firebaseio.com", + "exceptionUrl": "https://nst-manager-exceptions.firebaseio.com" + }, + "reports": { + "disVoiceZoneRprt": false, + "disVoiceUsageRprt": false + }, + "schedules": { + "count": 8 + }, + "streaming": { + "allowLocal": false + }, + "healthcheck": { + "camTimeout": 120, + "protWireTimeout": 45, + "protBattTimeout": 1500, + "tstatTimeout": 45, + "longTimeout": 120, + "timeout": 45, + "enabled": true, + "repairEnabled": false + }, + "maintenance": { + "stateVer": 3 + } + }, + "other": { + "active": 0, + "items": [{ + "id": "OWQxMzJlODMtMTFmYy00NWJlLTlhOGQtOTViN2E3Y2IwN2Ew", + "secret": "TERhSmU4dEFNdmRQR3lGUHQwSkpQMTY1eA==" + }, + { + "id": "MzFhZWE0NmMtNDA0OC00YzJiLWI2YmUtY2FjN2ZlMzA1ZDRj", + "secret": "Rm1PNDY5R1hmZFNWam43UGhLbmpHV1psbQ==" + }, + { + "id": "NjNlOWJlZmEtZGM2Mi00YjczLWFhZjQtZGNmMzgyNmRkNzA0", + "secret": "OGlxVDhYNDZ3YTJVWm5MMG9lM1RieU9hMA==" + } + ] + }, + "blacklists": { + "clients": [], + "metrics": [], + "exceptions": [] + } +} \ No newline at end of file diff --git a/Data/appData.json b/Data/appData.json index 6aeacc347..25fab44a1 100644 --- a/Data/appData.json +++ b/Data/appData.json @@ -24,38 +24,35 @@ "setupVersion": 2, "versions": { "app": { - "ver": "5.2.3" + "ver": "5.6.4" }, "autoapp": { - "ver": "5.2.0" + "ver": "5.5.0" + }, + "storapp": { + "ver": "5.4.0" }, "thermostat": { - "ver": "5.2.0" + "ver": "5.4.6" }, "protect": { - "ver": "5.2.0" + "ver": "5.4.3" }, "camera": { - "ver": "5.2.0" + "ver": "5.4.5" }, "presence": { - "ver": "5.2.0" + "ver": "5.4.4" }, "weather": { - "ver": "5.2.0" + "ver": "5.5.2" } }, "allowInApp": false }, - "html": { - "cssVer": 1, - "cssUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Documents/css/ST-HTML.min.css", - "chartJsVer": 1, - "chartJsUrl": "https://www.gstatic.com/charts/loader.js" - }, "database": { "allowRemoteDiag": true, - "disableExceptions": false, + "disableExceptions": true, "exceptionPath": "exceptionData", "newexceptionPath": "newexceptionData", "remoteDiagPath": "remoteDiagLogs" @@ -89,11 +86,11 @@ }, "healthcheck": { "camTimeout": 120, - "protWireTimeout": 35, + "protWireTimeout": 45, "protBattTimeout": 1500, - "tstatTimeout": 35, + "tstatTimeout": 45, "longTimeout": 120, - "timeout": 35, + "timeout": 45, "enabled": true, "repairEnabled": false }, @@ -101,4 +98,4 @@ "enabled": false, "path": "" } -} +} \ No newline at end of file diff --git a/Data/changelog.txt b/Data/changelog.txt index 2b2ccdb6a..6d103af8a 100644 --- a/Data/changelog.txt +++ b/Data/changelog.txt @@ -1,29 +1,50 @@ -V5.2.3 (November 8th, 2017): +V5.6.4 (May 16th, 2019): ▔▔▔▔▔▔▔▔▔▔▔ Manager App: - • FIXED: Empty Locations on New Installs - • FIXED: Tweaked the way app updates messages are determined - • ADDED: Workaround step added to stop the issues preventing users from uninstalling the App - • UPDATED: Minor Device Health Tweaks + • Token Updates -Automation App 5.1.8: -• FIXED: Tweaks to the Uninstall Process -• FIXED: More Cleanups +V5.6.2 (April 9th, 2019): +▔▔▔▔▔▔▔▔▔▔▔ +Manager App: + • Adjust for more conservative nest throttling + +V5.6.1 (March 29th, 2019): +▔▔▔▔▔▔▔▔▔▔▔ +Manager App: + • REMOVED: Local rest stream support (Until ST restores the feature) + • UPDATED: Simplified exception report logic. -V5.2.2 (November 7th, 2017): +V5.5.6 (November 14th, 2018): ▔▔▔▔▔▔▔▔▔▔▔ Manager App: - • FIXED: Minor Bug Fixes and Code Cleanups. + • Enabled Echo Speaks device support for Voice Notifications + • FIXED: Bug Fixes + +Automation App 5.4.7: + • FIXED: Bug Fixes -V5.2.1 (October 14th, 2017): +V5.5.2 (September 9th, 2018): ▔▔▔▔▔▔▔▔▔▔▔ Manager App: - • UPDATED: I have changed the app to no longer use our tokens and it will tell you when you are missing the required id and secret. + • Enabled new camera options + • FIXED: Bug Fixes + +Automation App 5.4.5: + • FIXED: Bug Fixes + +V5.5.1 (September 8th, 2018): +▔▔▔▔▔▔▔▔▔▔▔ +Manager App: + • FIXED: Bug Fixes + +Automation App 5.4.4: + • FIXED: Bug Fixes -V5.2.0 (July 22nd, 2017): +V5.5.0 (August 28th, 2018): ▔▔▔▔▔▔▔▔▔▔▔ Manager App: - • FIXED: NP issues + • UPDATED: NST Streaming is now communicates via local network (when enabled) + • FIXED: Bug Fixes -Automation App 5.1.7: -• FIXED: NP issues +Automation App 5.4.3: + • FIXED: Bug Fixes diff --git a/Data/changelog_cam.txt b/Data/changelog_cam.txt index 94a9bd92b..326e35303 100644 --- a/Data/changelog_cam.txt +++ b/Data/changelog_cam.txt @@ -1,15 +1,22 @@ -

V5.2.0 (November 8th, 2017):

+

V5.4.1 (September 8th, 2018):



-

V5.1.4 (July 21st, 2017):

+ +

V5.3.8 (July 30th, 2018):


+
+ +

V5.3.7 (July 4th, 2018):

+


+ diff --git a/Data/changelog_prot.txt b/Data/changelog_prot.txt index 4771bec79..87a7b5636 100644 --- a/Data/changelog_prot.txt +++ b/Data/changelog_prot.txt @@ -1,13 +1,22 @@ -

V5.2.0 (November 8th, 2017):

+

V5.4.1 (September 8th, 2018):



-

V5.1.1 (June 17th, 2017):

+ +

V5.3.6 (July 4th, 2018):


+
+ +

V5.3.5 (May 31st, 2018):

+


+ diff --git a/Data/changelog_tstat.txt b/Data/changelog_tstat.txt index 4f8580365..23b025dae 100644 --- a/Data/changelog_tstat.txt +++ b/Data/changelog_tstat.txt @@ -1,13 +1,22 @@ -

V5.2.0 (November 8th, 2017):

+

V5.4.1 (September 8th, 2018):



-

V5.1.6 (November 7th, 2017):

+ +

V5.3.6 (July 30th, 2018):


+
+ +

V5.3.6 (July 4th, 2018):

+


+ diff --git a/Data/changelog_weath.txt b/Data/changelog_weath.txt index baf0a48ee..79168fbae 100644 --- a/Data/changelog_weath.txt +++ b/Data/changelog_weath.txt @@ -1,13 +1,23 @@ -

V5.2.0 (November 8th, 2017):

+

V5.4.1 (Septemper 8th, 2018):



-

V5.1.2 (June 26th, 2017):

+ +

V5.3.6 (July 4th, 2018):


+
+ +

V5.3.5 (May 31st, 2018):

+


+ diff --git a/Documents/css/ST-HTML.css b/Documents/css/ST-HTML.css index 6cb3b346d..106bba2c1 100644 --- a/Documents/css/ST-HTML.css +++ b/Documents/css/ST-HTML.css @@ -1,25 +1,26 @@ body { - font-family: 'San Francisco', 'Roboto', 'Arial'; - margin:0; - font-size: 3.9vw; + font-family: 'San Francisco', 'Roboto', 'Arial'; + margin: 0; + font-size: 3.9vw; } div { - margin:1px; + margin: 1px; } input[type="radio"], input[type="checkbox"] { - /* hide the inputs */ - opacity: 0; + /* hide the inputs */ + opacity: 0; } -:checked + span { - /* style for the checked/selected state */ - border: 3px solid #444; - text-shadow: 1px 1px 0 rgba(0,0,0,0.4); +:checked+span { + /* style for the checked/selected state */ + border: 3px solid #444; + text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.4); } + /**.button { background-color: #00a1db; border: none; @@ -49,19 +50,18 @@ input[type="checkbox"] { } .container { - position: relative; - width: 100%; + position: relative; + width: 100%; } -.hideable{ - transition: all ease 2s; +.hideable { + transition: all ease 2s; } - fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } button, @@ -69,18 +69,26 @@ input, optgroup, select, textarea { - color: inherit; /* 1 */ - font: inherit; /* 2 */ - margin: 0; /* 3 */ + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } -h1, h2, h3, h4, h5, h6 { - padding:0px; - margin:0px; +h1, +h2, +h3, +h4, +h5, +h6 { + padding: 0px; + margin: 0px; } .topBorder { - border-top: 2px solid #00a1db; + border-top: 2px solid #00a1db; } .bottomBorder { @@ -88,149 +96,163 @@ h1, h2, h3, h4, h5, h6 { } h1 { - font-size: 6vw; - width: 100%; - text-align: center; - font-weight: normal; + font-size: 6vw; + width: 100%; + text-align: center; + font-weight: normal; } h2 { - font-size: 9vw; - text-align: center; - margin-left: auto; - margin-right: auto; - font-weight: normal; + font-size: 9vw; + text-align: center; + margin-left: auto; + margin-right: auto; + font-weight: normal; } - -h3, h3 a { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #B74C4C; - color: #f5f5f5; +h3, +h3 a { + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #B74C4C; + color: #f5f5f5; } h4 { - font-size: 4vw; - font-weight: bold; - text-align: center; - background: #00a1db; - color: #f5f5f5; + font-size: 4vw; + font-weight: bold; + text-align: center; + background: #00a1db; + color: #f5f5f5; } .centerText { - text-align: center; + text-align: center; } hr { - background: #00a1db; - width: 100%; - height: 1px; -} - -.topModal, .bottomModal { - position: fixed; - font-size: 3vw; - top: 0; - right: 0; - bottom: 0; - left: 0; - background: rgba(0,0,0,0.5); - z-index: 99999; - opacity:0; - -webkit-transition: opacity 400ms ease-in; - -moz-transition: opacity 400ms ease-in; - transition: opacity 400ms ease-in; - pointer-events: none; -} - -.topModal:target, .bottomModal:target { - opacity:1; - pointer-events: auto; -} - -.topModal > div { - width: 65%; - position: relative; - margin: 10% auto; - padding: 5px 20px 13px 20px; - border-radius: 10px; - background: #fff; -} - -.bottomModal > div { - width: 65%; - position: relative; - margin: 75% auto; - padding: 5px 20px 13px 20px; - border-radius: 10px; - background: #fff; + background: #00a1db; + width: 100%; + height: 1px; +} + +.topModal, +.bottomModal { + position: fixed; + font-size: 3vw; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 99999; + opacity: 0; + -webkit-transition: opacity 400ms ease-in; + -moz-transition: opacity 400ms ease-in; + transition: opacity 400ms ease-in; + pointer-events: none; +} + +.topModal:target, +.bottomModal:target { + opacity: 1; + pointer-events: auto; +} + +.topModal>div { + width: 65%; + position: relative; + margin: 10% auto; + padding: 5px 20px 13px 20px; + border-radius: 10px; + background: #fff; +} + +.bottomModal>div { + width: 65%; + position: relative; + margin: 75% auto; + padding: 5px 20px 13px 20px; + border-radius: 10px; + background: #fff; } .modal { - display: none; /* Hidden by default */ - position: fixed; /* Stay in place */ - z-index: 1; /* Sit on top */ - padding-top: 100px; /* Location of the box */ - left: 0; - top: 0; - width: 100%; /* Full width */ - height: 100%; /* Full height */ - overflow: auto; /* Enable scroll if needed */ - background-color: rgb(0,0,0); /* Fallback color */ - background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ + display: none; + /* Hidden by default */ + position: fixed; + /* Stay in place */ + z-index: 1; + /* Sit on top */ + padding-top: 100px; + /* Location of the box */ + left: 0; + top: 0; + width: 100%; + /* Full width */ + height: 100%; + /* Full height */ + overflow: auto; + /* Enable scroll if needed */ + background-color: rgb(0, 0, 0); + /* Fallback color */ + background-color: rgba(0, 0, 0, 0.4); + /* Black w/ opacity */ } .modal-content { - background-color: #fefefe; - margin: auto; - padding: 20px; - border: 1px solid #888; - width: 80%; + background-color: #fefefe; + margin: auto; + padding: 20px; + border: 1px solid #888; + width: 80%; } .close { - background: #606061; - color: #FFFFFF; - line-height: 25px; - position: absolute; - right: -12px; - text-align: center; - top: -10px; - width: 24px; - text-decoration: none; - font-weight: bold; - -webkit-border-radius: 12px; - -moz-border-radius: 12px; - border-radius: 12px; - -moz-box-shadow: 1px 1px 3px #000; - -webkit-box-shadow: 1px 1px 3px #000; - box-shadow: 1px 1px 3px #000; + background: #606061; + color: #FFFFFF; + line-height: 25px; + position: absolute; + right: -12px; + text-align: center; + top: -10px; + width: 24px; + text-decoration: none; + font-weight: bold; + -webkit-border-radius: 12px; + -moz-border-radius: 12px; + border-radius: 12px; + -moz-box-shadow: 1px 1px 3px #000; + -webkit-box-shadow: 1px 1px 3px #000; + box-shadow: 1px 1px 3px #000; } -.close:hover { background: #00d9ff; } +.close:hover { + background: #00d9ff; +} - table { - border: none; - border-radius: 3px; - width:100%; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; +table { + border: none; + border-radius: 3px; + width: 100%; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; } -th, td { - box-shadow: inset 0 0px rgba(0, 0, 0, 0.25), inset 0 0px rgba(0, 0, 0, 0.25); - padding: 4px; +th, +td { + box-shadow: inset 0 0px rgba(0, 0, 0, 0.25), inset 0 0px rgba(0, 0, 0, 0.25); + padding: 4px; } th { - -webkit-font-smoothing: antialiased; - color: #f5f5f5; - text-shadow: 0 0 1px rgba(0, 0, 0, 0.1); - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - background: #00a1db; + -webkit-font-smoothing: antialiased; + color: #f5f5f5; + text-shadow: 0 0 1px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + background: #00a1db; } .devInfo th { @@ -238,19 +260,19 @@ th { } td { - color: grey; - text-shadow: 0 0 1px rgba(255, 255, 255, 0.1); - text-align: center; + color: grey; + text-shadow: 0 0 1px rgba(255, 255, 255, 0.1); + text-align: center; } tr { - -webkit-transition: background 0.3s, box-shadow 0.3s; - -moz-transition: background 0.3s, box-shadow 0.3s; - transition: background 0.3s, box-shadow 0.3s; + -webkit-transition: background 0.3s, box-shadow 0.3s; + -moz-transition: background 0.3s, box-shadow 0.3s; + transition: background 0.3s, box-shadow 0.3s; } .dateTimeText { - font-size: 3.4vw; + font-size: 3.4vw; } .dateTimeTextSmall { @@ -258,74 +280,146 @@ tr { } .battImg { - width:30px; height:15px; + width: 30px; + height: 15px; } .leafImg { - width: 25px; - height: 25px; + width: 25px; + height: 25px; } .column, .columns { - width: 100%; - float: left; - box-sizing: border-box; + width: 100%; + float: left; + box-sizing: border-box; } .one.column, -.one.columns { width: 4.66666666667%; } -.two.columns { width: 13.3333333333%; } -.three.columns { width: 22%; } -.four.columns { width: 32.6666666667%; } -.five.columns { width: 39.3333333333%; } -.six.columns { width: 48%; } -.seven.columns { width: 56.6666666667%; } -.eight.columns { width: 65.3333333333%; } -.nine.columns { width: 74.0%; } -.ten.columns { width: 82.6666666667%; } -.eleven.columns { width: 91.3333333333%; } -.twelve.columns { width: 100%; margin-left: 0; } +.one.columns { + width: 4.66666666667%; +} + +.two.columns { + width: 13.3333333333%; +} + +.three.columns { + width: 22%; +} + +.four.columns { + width: 32.6666666667%; +} + +.five.columns { + width: 39.3333333333%; +} + +.six.columns { + width: 48%; +} + +.seven.columns { + width: 56.6666666667%; +} + +.eight.columns { + width: 65.3333333333%; +} + +.nine.columns { + width: 74.0%; +} + +.ten.columns { + width: 82.6666666667%; +} + +.eleven.columns { + width: 91.3333333333%; +} + +.twelve.columns { + width: 100%; + margin-left: 0; +} /* Offsets */ + .offset-by-one.column, -.offset-by-one.columns { margin-left: 8.66666666667%; } +.offset-by-one.columns { + margin-left: 8.66666666667%; +} + .offset-by-two.column, -.offset-by-two.columns { margin-left: 17.3333333333%; } +.offset-by-two.columns { + margin-left: 17.3333333333%; +} + .offset-by-three.column, -.offset-by-three.columns { margin-left: 26%; } +.offset-by-three.columns { + margin-left: 26%; +} + .offset-by-four.column, -.offset-by-four.columns { margin-left: 34.6666666667%; } +.offset-by-four.columns { + margin-left: 34.6666666667%; +} + .offset-by-five.column, -.offset-by-five.columns { margin-left: 43.3333333333%; } +.offset-by-five.columns { + margin-left: 43.3333333333%; +} + .offset-by-six.column, -.offset-by-six.columns { margin-left: 52%; } +.offset-by-six.columns { + margin-left: 52%; +} + .offset-by-seven.column, -.offset-by-seven.columns { margin-left: 60.6666666667%; } +.offset-by-seven.columns { + margin-left: 60.6666666667%; +} + .offset-by-eight.column, -.offset-by-eight.columns { margin-left: 69.3333333333%; } +.offset-by-eight.columns { + margin-left: 69.3333333333%; +} + .offset-by-nine.column, -.offset-by-nine.columns { margin-left: 78.0%; } +.offset-by-nine.columns { + margin-left: 78.0%; +} + .offset-by-ten.column, -.offset-by-ten.columns { margin-left: 86.6666666667%; } -.offset-by-eleven.column, -.offset-by-eleven.columns { margin-left: 95.3333333333%; } +.offset-by-ten.columns { + margin-left: 86.6666666667%; +} +.offset-by-eleven.column, +.offset-by-eleven.columns { + margin-left: 95.3333333333%; +} .container:after, .row:after, .u-cf { - content: ""; - display: table; - clear: both; } + content: ""; + display: table; + clear: both; +} .row { - width:100%; - margin:2px; + width: 100%; + margin: 2px; } + /*<--Bootstrap button -->*/ + .btn { display: inline-block; padding: 6px 12px; @@ -337,138 +431,172 @@ tr { white-space: nowrap; vertical-align: middle; -ms-touch-action: manipulation; - touch-action: manipulation; + touch-action: manipulation; cursor: pointer; -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; background-image: none; border: 1px solid transparent; border-radius: 4px; } + .btn-info { - color: #fff; - background-color: #00a1db; - border-color: #00a1db; + color: #fff; + background-color: #00a1db; + border-color: #00a1db; } -.red{ - background-color:#db3a00; +.red { + background-color: #db3a00; } -.yellow{ - background-color:#dba800; +.yellow { + background-color: #dba800; } .redAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #B74C4C; - color: #f5f5f5; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #B74C4C; + color: #f5f5f5; + padding: 8px 0px; } .brightRedAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #ff3b19; - color: #f5f5f5; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #ff3b19; + color: #f5f5f5; + padding: 8px 0px; } .greenAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #00ff00; - -webkit-text-stroke: 1.0px #000000; - -webkit-text-fill-color: #FFFFFF; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #00ff00; + -webkit-text-stroke: 1.0px #000000; + -webkit-text-fill-color: #FFFFFF; + padding: 8px 0px; } .androidAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #6f786f; - -webkit-text-stroke: 1.0px #000000; - -webkit-text-fill-color: #FFFFFF; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #6f786f; + -webkit-text-stroke: 1.0px #000000; + -webkit-text-fill-color: #FFFFFF; + padding: 8px 0px; } .orangeAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #ffae19; - color: #f5f5f5; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #ffae19; + color: #f5f5f5; + padding: 8px 0px; } .blueTitle { - font-size: 4vw; - font-weight: bold; - text-align: center; - background: #00a1db; - color: #f5f5f5; + font-size: 4vw; + font-weight: bold; + text-align: center; + background: #00a1db; + color: #f5f5f5; } .alertModalTitle { - font-size: 22px; - font-weight: bold; - text-align: center; - background: transparent; - color: black; + font-size: 22px; + font-weight: bold; + text-align: center; + background: transparent; + color: black; } .sched h3 { - font-size: 4.6vw; - background: #00a1db; + font-size: 4.6vw; + background: #00a1db; } .sched h4 { - font-size: 3.8vw; - background: #00a1db; + font-size: 3.8vw; + background: #00a1db; } .sched col { - font-size: 4.0vw; + font-size: 4.0vw; } .slideFooterMsg { font-size: 3.0vw; padding: 20px; - margin:1em auto; + margin: 1em auto; } .pageFooterBtn { padding: 10px; - horizontal-align: center; + /* horizontal-align: center; */ text-align: center; } .schedFill { - background: gray; - color: white; - text-align: center; - padding: 4px; + background: gray; + color: white; + text-align: center; + padding: 4px; } .tempSrc th { - font-size: 4.1vw; - font-weight: bold; - background: transparent; - text-decoration: underline; - color: gray; + font-size: 4.1vw; + font-weight: bold; + background: transparent; + text-decoration: underline; + color: gray; +} + +.slideFooterBtn { + font-size: 1rem; + text-align: center; + padding: 0; +} + +.slideFooterText { + font-size: 3.0vw; + margin: 1em auto; + padding: 0; + text-decoration: underline; +} + +.pageFooterCls { + text-align: center; } .swiper-container { width: 95%; min-height: 300px; - padding: 10px; + padding: 0 10px !important; +} + +.swiper-pagination-bullet { + width: 20px; + height: 20px; + text-align: center; + line-height: 20px; + font-size: 10px; + color: #000; + opacity: 1; + background: rgba(0, 0, 0, 0.2); +} + +.swiper-pagination-bullet-active { + color: #fff; + background: #007aff; } .default-container { @@ -477,12 +605,14 @@ tr { } .vex.vex-theme-default .vex-content { - width: 95%; padding: 3px; + width: 95%; + padding: 3px; } .alarmImg { - vertical-align: top; - width:60px; height:60px; + vertical-align: top; + width: 60px; + height: 60px; } .alarmWarnCap { @@ -501,7 +631,7 @@ tr { } .sectionBg { - box-shadow: 0 1px 1px rgba(0,0,0,0.16), 0 1px 1px rgba(0,0,0,0.23); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.16), 0 1px 1px rgba(0, 0, 0, 0.23); background: white; } @@ -513,7 +643,7 @@ tr { } .sectionBg table { - box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); background: white; } @@ -543,11 +673,13 @@ tr { background: transparent; } -.chgLog ul, li { +.chgLog ul, +li { font-size: 12px; padding: 0 10px 0 10px; Margin: 0; } + .chgLog p { font-size: 12px; -} +} \ No newline at end of file diff --git a/Documents/css/ST-HTML.min.css b/Documents/css/ST-HTML.min.css index 7b6bb13ad..33096e6c7 100644 --- a/Documents/css/ST-HTML.min.css +++ b/Documents/css/ST-HTML.min.css @@ -1 +1 @@ -body{font-family:'San Francisco','Roboto','Arial';margin:0;font-size:3.9vw}div{margin:1px}input[type="radio"],input[type="checkbox"]{opacity:0}:checked+span{border:3px solid #444;text-shadow:1px 1px 0 rgba(0,0,0,0.4)}.button{background:white;background-image:linear-gradient(rgba(255,255,255,0),rgba(0,0,0,0.1));border:1px solid #ccc;border-radius:5px;color:#404040;display:block;width:30%;padding:.5em;outline:0}.container{position:relative;width:100%}.hideable{transition:all ease 2s}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}h1,h2,h3,h4,h5,h6{padding:0;margin:0}.topBorder{border-top:2px solid #00a1db}.bottomBorder{border-bottom:2px solid #808080}h1{font-size:6vw;width:100%;text-align:center;font-weight:normal}h2{font-size:9vw;text-align:center;margin-left:auto;margin-right:auto;font-weight:normal}h3,h3 a{font-size:6vw;font-weight:bold;text-align:center;background:#b74c4c;color:#f5f5f5}h4{font-size:4vw;font-weight:bold;text-align:center;background:#00a1db;color:#f5f5f5}.centerText{text-align:center}hr{background:#00a1db;width:100%;height:1px}.topModal,.bottomModal{position:fixed;font-size:3vw;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,0.5);z-index:99999;opacity:0;-webkit-transition:opacity 400ms ease-in;-moz-transition:opacity 400ms ease-in;transition:opacity 400ms ease-in;pointer-events:none}.topModal:target,.bottomModal:target{opacity:1;pointer-events:auto}.topModal>div{width:65%;position:relative;margin:10% auto;padding:5px 20px 13px 20px;border-radius:10px;background:#fff}.bottomModal>div{width:65%;position:relative;margin:75% auto;padding:5px 20px 13px 20px;border-radius:10px;background:#fff}.modal{display:none;position:fixed;z-index:1;padding-top:100px;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,0.4)}.modal-content{background-color:#fefefe;margin:auto;padding:20px;border:1px solid #888;width:80%}.close{background:#606061;color:#fff;line-height:25px;position:absolute;right:-12px;text-align:center;top:-10px;width:24px;text-decoration:none;font-weight:bold;-webkit-border-radius:12px;-moz-border-radius:12px;border-radius:12px;-moz-box-shadow:1px 1px 3px #000;-webkit-box-shadow:1px 1px 3px #000;box-shadow:1px 1px 3px #000}.close:hover{background:#00d9ff}table{border:0;border-radius:3px;width:100%;-webkit-border-radius:3px;-moz-border-radius:3px}th,td{box-shadow:inset 0 0 rgba(0,0,0,0.25),inset 0 0 rgba(0,0,0,0.25);padding:4px}th{-webkit-font-smoothing:antialiased;color:#f5f5f5;text-shadow:0 0 1px rgba(0,0,0,0.1);-webkit-border-radius:2px;-moz-border-radius:2px;background:#00a1db}.devInfo th{font-size:3.8vw}td{color:grey;text-shadow:0 0 1px rgba(255,255,255,0.1);text-align:center}tr{-webkit-transition:background .3s,box-shadow .3s;-moz-transition:background .3s,box-shadow .3s;transition:background .3s,box-shadow .3s}.dateTimeText{font-size:3.4vw}.dateTimeTextSmall{font-size:2.8vw}.battImg{width:30px;height:15px}.leafImg{width:25px;height:25px}.column,.columns{width:100%;float:left;box-sizing:border-box}.one.column,.one.columns{width:4.66666666667%}.two.columns{width:13.3333333333%}.three.columns{width:22%}.four.columns{width:32.6666666667%}.five.columns{width:39.3333333333%}.six.columns{width:48%}.seven.columns{width:56.6666666667%}.eight.columns{width:65.3333333333%}.nine.columns{width:74.0%}.ten.columns{width:82.6666666667%}.eleven.columns{width:91.3333333333%}.twelve.columns{width:100%;margin-left:0}.offset-by-one.column,.offset-by-one.columns{margin-left:8.66666666667%}.offset-by-two.column,.offset-by-two.columns{margin-left:17.3333333333%}.offset-by-three.column,.offset-by-three.columns{margin-left:26%}.offset-by-four.column,.offset-by-four.columns{margin-left:34.6666666667%}.offset-by-five.column,.offset-by-five.columns{margin-left:43.3333333333%}.offset-by-six.column,.offset-by-six.columns{margin-left:52%}.offset-by-seven.column,.offset-by-seven.columns{margin-left:60.6666666667%}.offset-by-eight.column,.offset-by-eight.columns{margin-left:69.3333333333%}.offset-by-nine.column,.offset-by-nine.columns{margin-left:78.0%}.offset-by-ten.column,.offset-by-ten.columns{margin-left:86.6666666667%}.offset-by-eleven.column,.offset-by-eleven.columns{margin-left:95.3333333333%}.container:after,.row:after,.u-cf{content:"";display:table;clear:both}.row{width:100%;margin:2px}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn-info{color:#fff;background-color:#00a1db;border-color:#00a1db}.red{background-color:#db3a00}.yellow{background-color:#dba800}.redAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#b74c4c;color:#f5f5f5;padding:8px 0}.brightRedAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#ff3b19;color:#f5f5f5;padding:8px 0}.greenAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#0f0;-webkit-text-stroke:1.0px #000;-webkit-text-fill-color:#fff;padding:8px 0}.androidAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#6f786f;-webkit-text-stroke:1.0px #000;-webkit-text-fill-color:#fff;padding:8px 0}.orangeAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#ffae19;color:#f5f5f5;padding:8px 0}.blueTitle{font-size:4vw;font-weight:bold;text-align:center;background:#00a1db;color:#f5f5f5}.alertModalTitle{font-size:22px;font-weight:bold;text-align:center;background:transparent;color:black}.sched h3{font-size:4.6vw;background:#00a1db}.sched h4{font-size:3.8vw;background:#00a1db}.sched col{font-size:4.0vw}.slideFooterMsg{font-size:3.0vw;padding:20px;margin:1em auto}.pageFooterBtn{padding:10px;horizontal-align:center;text-align:center}.schedFill{background:gray;color:white;text-align:center;padding:4px}.tempSrc th{font-size:4.1vw;font-weight:bold;background:transparent;text-decoration:underline;color:gray}.swiper-container{width:95%;min-height:300px;padding:10px}.default-container{width:95%;padding:10px}.vex.vex-theme-default .vex-content{width:95%;padding:3px}.alarmImg{vertical-align:top;width:60px;height:60px}.alarmWarnCap{display:block;color:#e89a15}.alarmEmerCap{display:block;color:#df5316}.alarmClearCap{display:block;color:gray}.sectionBg{box-shadow:0 1px 1px rgba(0,0,0,0.16),0 1px 1px rgba(0,0,0,0.23);background:white}.sectionBg h3{background-color:#00a1db;font-size:4.5vw;padding:.6vw;text-shadow:1px 1px 1px black}.sectionBg table{box-shadow:0 3px 6px rgba(0,0,0,0.16),0 3px 6px rgba(0,0,0,0.23);background:white}.devInfo th{color:#00a1db;background:transparent;font-size:3.8vw;text-shadow:0 0 1px lightgray;text-decoration:underline}.redText{color:red}.orangeText{color:orange}.chgLog div{padding:0 5px 0 5px;text-align:left}.chgLog h3{background-color:transparent;background:transparent}.chgLog ul,li{font-size:12px;padding:0 10px 0 10px;Margin:0}.chgLog p{font-size:12px} \ No newline at end of file +.androidAlertBanner,.greenAlertBanner{-webkit-text-stroke:1px #000;-webkit-text-fill-color:#FFF}body{font-family:'San Francisco',Roboto,Arial;margin:0;font-size:3.9vw}div{margin:1px}input[type=radio],input[type=checkbox]{opacity:0}:checked+span{border:3px solid #444;text-shadow:1px 1px 0 rgba(0,0,0,.4)}.button{background:#fff;background-image:linear-gradient(rgba(255,255,255,0),rgba(0,0,0,.1));border:1px solid #ccc;border-radius:5px;color:#404040;display:block;width:30%;padding:.5em;outline:0}h4,hr{background:#00a1db}h3,h3 a,h4{color:#f5f5f5}.container,h1,hr{width:100%}.container{position:relative}.hideable{transition:all ease 2s}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}h1,h2{text-align:center;font-weight:400}h1,h2,h3,h4,h5,h6{padding:0;margin:0}.topBorder{border-top:2px solid #00a1db}.bottomBorder{border-bottom:2px solid grey}h1{font-size:6vw}h2{font-size:9vw;margin-left:auto;margin-right:auto}.close,h3,h3 a,h4{font-weight:700;text-align:center}h3,h3 a{font-size:6vw;background:#B74C4C}h4{font-size:4vw}.centerText{text-align:center}hr{height:1px}.bottomModal,.topModal{position:fixed;font-size:3vw;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.5);z-index:99999;opacity:0;-webkit-transition:opacity .4s ease-in;-moz-transition:opacity .4s ease-in;transition:opacity .4s ease-in;pointer-events:none}.bottomModal>div,.topModal>div{width:65%;position:relative;padding:5px 20px 13px;border-radius:10px;background:#fff}.bottomModal:target,.topModal:target{opacity:1;pointer-events:auto}.topModal>div{margin:10% auto}.bottomModal>div{margin:75% auto}.modal{display:none;position:fixed;z-index:1;padding-top:100px;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,.4)}.modal-content{background-color:#fefefe;margin:auto;padding:20px;border:1px solid #888;width:80%}.close{background:#606061;color:#FFF;line-height:25px;position:absolute;right:-12px;top:-10px;width:24px;text-decoration:none;-webkit-border-radius:12px;-moz-border-radius:12px;border-radius:12px;-moz-box-shadow:1px 1px 3px #000;-webkit-box-shadow:1px 1px 3px #000;box-shadow:1px 1px 3px #000}.devInfo th,.slideFooterText,.tempSrc th{text-decoration:underline}.close:hover{background:#00d9ff}table{border:none;border-radius:3px;width:100%;-webkit-border-radius:3px;-moz-border-radius:3px}td,th{box-shadow:inset 0 0 rgba(0,0,0,.25),inset 0 0 rgba(0,0,0,.25);padding:4px}th{-webkit-font-smoothing:antialiased;color:#f5f5f5;text-shadow:0 0 1px rgba(0,0,0,.1);-webkit-border-radius:2px;-moz-border-radius:2px;background:#00a1db}td{color:grey;text-shadow:0 0 1px rgba(255,255,255,.1);text-align:center}tr{-webkit-transition:background .3s,box-shadow .3s;-moz-transition:background .3s,box-shadow .3s;transition:background .3s,box-shadow .3s}.dateTimeText{font-size:3.4vw}.dateTimeTextSmall{font-size:2.8vw}.battImg{width:30px;height:15px}.leafImg{width:25px;height:25px}.column,.columns{width:100%;float:left;box-sizing:border-box}.one.column,.one.columns{width:4.66666666667%}.two.columns{width:13.3333333333%}.three.columns{width:22%}.four.columns{width:32.6666666667%}.five.columns{width:39.3333333333%}.six.columns{width:48%}.seven.columns{width:56.6666666667%}.eight.columns{width:65.3333333333%}.nine.columns{width:74%}.ten.columns{width:82.6666666667%}.eleven.columns{width:91.3333333333%}.twelve.columns{width:100%;margin-left:0}.offset-by-one.column,.offset-by-one.columns{margin-left:8.66666666667%}.offset-by-two.column,.offset-by-two.columns{margin-left:17.3333333333%}.offset-by-three.column,.offset-by-three.columns{margin-left:26%}.offset-by-four.column,.offset-by-four.columns{margin-left:34.6666666667%}.offset-by-five.column,.offset-by-five.columns{margin-left:43.3333333333%}.offset-by-six.column,.offset-by-six.columns{margin-left:52%}.offset-by-seven.column,.offset-by-seven.columns{margin-left:60.6666666667%}.offset-by-eight.column,.offset-by-eight.columns{margin-left:69.3333333333%}.offset-by-nine.column,.offset-by-nine.columns{margin-left:78%}.offset-by-ten.column,.offset-by-ten.columns{margin-left:86.6666666667%}.offset-by-eleven.column,.offset-by-eleven.columns{margin-left:95.3333333333%}.container:after,.row:after,.u-cf{content:"";display:table;clear:both}.row{width:100%;margin:2px}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.androidAlertBanner,.brightRedAlertBanner,.greenAlertBanner,.orangeAlertBanner,.redAlertBanner{font-size:6vw;padding:8px 0}.btn-info{color:#fff;background-color:#00a1db;border-color:#00a1db}.blueTitle,.brightRedAlertBanner,.orangeAlertBanner,.redAlertBanner{color:#f5f5f5;font-weight:700;text-align:center}.red{background-color:#db3a00}.yellow{background-color:#dba800}.redAlertBanner{background:#B74C4C}.brightRedAlertBanner{background:#ff3b19}.greenAlertBanner{font-weight:700;text-align:center;background:#0f0}.androidAlertBanner{font-weight:700;text-align:center;background:#6f786f}.orangeAlertBanner{background:#ffae19}.blueTitle{font-size:4vw;background:#00a1db}.alertModalTitle{font-size:22px;font-weight:700;text-align:center;background:0 0;color:#000}.sched h3{font-size:4.6vw;background:#00a1db}.sched h4{font-size:3.8vw;background:#00a1db}.sched col{font-size:4vw}.slideFooterMsg{font-size:3vw;padding:20px;margin:1em auto}.pageFooterBtn{padding:10px;text-align:center}.schedFill{background:gray;color:#fff;text-align:center;padding:4px}.tempSrc th{font-size:4.1vw;font-weight:700;background:0 0;color:gray}.slideFooterBtn{font-size:1rem;text-align:center;padding:0}.slideFooterText{font-size:3vw;margin:1em auto;padding:0}.pageFooterCls{text-align:center}.swiper-container{width:95%;min-height:300px;padding:0 10px!important}.swiper-pagination-bullet{width:20px;height:20px;text-align:center;line-height:20px;font-size:10px;color:#000;opacity:1;background:rgba(0,0,0,.2)}.swiper-pagination-bullet-active{color:#fff;background:#007aff}.default-container{width:95%;padding:10px}.vex.vex-theme-default .vex-content{width:95%;padding:3px}.alarmImg{vertical-align:top;width:60px;height:60px}.alarmWarnCap{display:block;color:#e89a15}.alarmEmerCap{display:block;color:#df5316}.alarmClearCap{display:block;color:gray}.sectionBg{box-shadow:0 1px 1px rgba(0,0,0,.16),0 1px 1px rgba(0,0,0,.23);background:#fff}.sectionBg h3{background-color:#00a1db;font-size:4.5vw;padding:.6vw;text-shadow:1px 1px 1px #000}.sectionBg table{box-shadow:0 3px 6px rgba(0,0,0,.16),0 3px 6px rgba(0,0,0,.23);background:#fff}.chgLog h3,.devInfo th{background:0 0}.devInfo th{color:#00a1db;font-size:3.8vw;text-shadow:0 0 1px #d3d3d3}.chgLog p,.chgLog ul,li{font-size:12px}.redText{color:red}.orangeText{color:orange}.chgLog div{padding:0 5px;text-align:left}.chgLog ul,li{padding:0 10px;Margin:0} \ No newline at end of file diff --git a/Documents/css/diaghome.css b/Documents/css/diaghome.css index 61fe1d42d..d9d89312d 100644 --- a/Documents/css/diaghome.css +++ b/Documents/css/diaghome.css @@ -64,7 +64,7 @@ body { } .shortcutBtns { - width: 140px; + width: 150px; } .stateUseCircText { @@ -79,7 +79,8 @@ body { font-size: 14px; } -.percircle.blue2 .bar, .percircle.blue2 .fill { +.percircle.blue2 .bar, +.percircle.blue2 .fill { border-color: #049dff; } @@ -87,7 +88,8 @@ body { color: #049dff; } -.percircle.blue2.dark .bar, .percircle.blue2.dark .fill { +.percircle.blue2.dark .bar, +.percircle.blue2.dark .fill { border-color: #049dff; } @@ -160,6 +162,7 @@ body { border-width: 1px; } + /************************************** BACK TO TOP CSS BUTTON ***************************************/ @@ -181,4 +184,4 @@ body { #scrollTopBtn:hover { background-color: #3174AE; -} +} \ No newline at end of file diff --git a/Documents/css/diaghome.min.css b/Documents/css/diaghome.min.css index f489b7dd8..087a37a27 100644 --- a/Documents/css/diaghome.min.css +++ b/Documents/css/diaghome.min.css @@ -1 +1 @@ -html{position:relative;min-height:100%;min-width:375px}body{margin-bottom:20px}.container{width:auto;max-width:800px;padding:0 15px}#top-hdr{height:auto;min-width:375px}.in-middle{vertical-align:middle}.left-head-col{padding:1.2em 0 0 20px}.right-head-col{padding:1.8em 40px 0 0}.centerText{text-align:center}.links{padding:10px;font-size:18px}.footer{position:relative;bottom:0;width:100%;max-width:800px;height:20px;line-height:20px;padding-bottom:50px}.footerText{text-align:center;font-size:14px}.logoIcn{width:1.7em;height:auto;max-width:48px;max-height:48px}.shortcutBtns{width:140px}.stateUseCircText{text-align:center;color:gray;font-size:13px}.stateUseTitleText{text-align:center;color:black;font-size:14px}.percircle.blue2 .bar,.percircle.blue2 .fill{border-color:#049dff}.percircle.blue2:hover>span{color:#049dff}.percircle.blue2.dark .bar,.percircle.blue2.dark .fill{border-color:#049dff}.percircle.blue2.dark:hover>span{color:#049dff}.refresh-btn{color:black;width:auto;height:auto;max-width:90px;max-height:40px;font-size:1.0em;border-radius:.4em;background-color:white;border-color:gray;border-style:solid;border-width:1px}#rfrshBtn:after{content:' Refresh'}@media screen and (max-width:520px){#rfrshBtn:after{content:''}#rfrshBtn{font-size:1.1em}}.panel-title-text{font-size:24px}.subpanel-title-text{font-size:18px}.panel-border{padding:0 15px;border-radius:1em;border-style:solid;border-color:lightgray;border-style:solid;border-width:1px}.install-content{padding:7px 0 0 0}.title-text{font-size:2.0em}.home-btn{width:auto;height:auto;max-width:80px;max-height:40px;font-size:1.1em;border-radius:.4em;background-color:white;border-color:gray;border-style:solid;border-width:1px}#scrollTopBtn{display:none;position:fixed;bottom:20px;right:30px;z-index:99;border:0;outline:0;background-color:gray;color:white;cursor:pointer;padding:15px;border-radius:10px}#scrollTopBtn:hover{background-color:#3174ae} \ No newline at end of file +#top-hdr,html{min-width:375px}.footer,html{position:relative}.centerText,.footerText,.stateUseCircText{text-align:center}.percircle.blue2 .bar,.percircle.blue2 .fill,.percircle.blue2.dark .bar,.percircle.blue2.dark .fill{border-color:#049dff}html{min-height:100%}body{margin-bottom:20px}.container{width:auto;max-width:800px;padding:0 15px}#top-hdr{height:auto}.in-middle{vertical-align:middle}.left-head-col{padding:1.2em 0 0 20px}.right-head-col{padding:1.8em 40px 0 0}.links{padding:10px;font-size:18px}.footer{bottom:0;width:100%;max-width:800px;height:20px;line-height:20px;padding-bottom:50px}.footerText{font-size:14px}.logoIcn{width:1.7em;height:auto;max-width:48px;max-height:48px}.shortcutBtns{width:150px}.home-btn,.refresh-btn{width:auto;height:auto;max-height:40px;background-color:#fff;border-style:solid;border-width:1px}.stateUseCircText{color:gray;font-size:13px}.stateUseTitleText{text-align:center;color:#000;font-size:14px}.percircle.blue2.dark:hover>span,.percircle.blue2:hover>span{color:#049dff}.refresh-btn{color:#000;max-width:90px;font-size:1em;border-radius:.4em;border-color:gray}#rfrshBtn:after{content:' Refresh'}@media screen and (max-width:520px){#rfrshBtn:after{content:''}#rfrshBtn{font-size:1.1em}}.panel-title-text{font-size:24px}.subpanel-title-text{font-size:18px}.panel-border{padding:0 15px;border-radius:1em;border-color:#d3d3d3;border-style:solid;border-width:1px}.install-content{padding:7px 0 0}.title-text{font-size:2em}.home-btn{max-width:80px;font-size:1.1em;border-radius:.4em;border-color:gray}#scrollTopBtn{display:none;position:fixed;bottom:20px;right:30px;z-index:99;border:none;outline:0;background-color:gray;color:#fff;cursor:pointer;padding:15px;border-radius:10px}#scrollTopBtn:hover{background-color:#3174AE} \ No newline at end of file diff --git a/Documents/css/diagpages.css b/Documents/css/diagpages.css index 8208619e1..c65ceb49f 100644 --- a/Documents/css/diagpages.css +++ b/Documents/css/diagpages.css @@ -69,1067 +69,16 @@ html, body { #rfrshBtn { font-size: 1.1em; } - body { padding:0px; margin:0; } - } -.export-pdf-btn { - color: white; - width: auto; - height: auto; - max-width: 90px; - max-height: 40px; - font-size: 1.0em; - border-radius: 0.4em; - background-color: transparent; - border-color: white; - border-style: solid; - border-width: 1px; - display: none; -} - -.panel-title-text { - padding-top: 0.5em; - font-size: 24px; -} - -.subpanel-title-text { - font-size: 18px; -} - -.panelHeadTxt { - font-size: 25px; -} - -.pnl-head-title { - font-size: 2.0em; -} - -@media (min-width: 800px) { - .pnl-head-title { - padding: 3px 0; - } -} - -@media (min-width: 600px) { - .pnl-head-title { - padding: 5px 0; - } -} - -.title-text { - font-size: 2.0em; -} - - -/************************************** - PRE CODE CSS -***************************************/ - -pre { - overflow-x: auto; - overflow-y: auto; -} - - -/************************************** - NAV BAR CSS -***************************************/ - -.navMenu { - text-align: left; -} - -.nav-home-btn { - padding: 20px 10px 0 10px; - font-size: 22px; -} - -.nav-menu { - padding: 12px; -} - -.nav-menu li { - border-bottom: solid 1px rgba(102, 102, 102, 0.3); - margin-left: 5px; - margin-right: 5px; - font-size: 14px; - padding: 12px; -} - -.nav-menu li a { - color: white; - text-decoration: none; -} - -.nav-menu li a:hover { - color: tomato; - text-decoration: none; -} - -.nav-menu li .sub-nav { - border-bottom: 0px; - padding: 4px; -} - -.nav-menu a .caret { - width: 0; - height: 0; - display: inline-block; - vertical-align: top; - border-top: 4px solid #4f5963; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; - margin-top: 8px; -} - -.nav-menu a:hover .caret { - border-top-color: #4f5963; -} - -.nav-menu li.open>a>.caret { - border-top: none; - border-bottom: 4px solid #4f5963; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} - -.nav-menu li.open>a:hover>.caret { - border-bottom-color: #4f5963; -} - -.icon:before { - font-family: 'FontAwesome'; - font-style: normal; - font-variant: normal; - font-weight: normal; - line-height: 1; - text-transform: none; - content: '\f105'; -} - -.nav-menu li>a>span.icon { - float: right; - margin: 0.1em 1.7em -0.1em 0; - opacity: 0; - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -.nav-menu li>a:hover>span.icon { - float: right; - margin: 0.1em 0.8em -0.1em 0; - opacity: 1; -} - -.menu-btn:focus { - outline: none; -} - -.nav-cont-bord-div { - padding: 15px 15px 25px 15px; -} - -.nav-cont-div { - padding: 10px; - border-radius: 0.6em; - background-color: #333333; - border: solid lightgray 1px; - -moz-box-shadow: 0px 5px 1px #ccc; - -webkit-box-shadow: 0px 1px 1px #ccc; - box-shadow: 0px 1px 1px #ccc; -} - -.nav-key-item { - font-weight: bold; - text-decoration: underline; - list-style: none; - font-size: 1.0em; -} - -.nav-subkey-item { - font-weight: normal; - list-style: none; -} - -.nav-subkey-item:before { - color: white; - content: "▶"; - padding-right: 8px; -} - - -/* Menu Appearance */ - -.pushy { - position: fixed; - width: 250px; - height: 100%; - top: 0; - z-index: 9999; - background: #191918; - overflow: auto; - -webkit-overflow-scrolling: touch; - /* enables momentum scrolling in iOS overflow elements */ -} - - -/* -.pushy a { - display: block; - color: #b3b3b1; - padding: 15px 30px; - text-decoration: none; -} - -.pushy a:hover { - color: #FFF; -} - -.pushy ul:first-child { - margin-top: 10px; -} -*/ - -.pushy.pushy-left { - left: 0; -} - -.pushy.pushy-right { - right: 0; -} - - -/*.pushy-content { - visibility: hidden; -}*/ - - -/* Menu Movement */ - -.pushy-left { - -webkit-transform: translate3d(-250px, 0, 0); - -ms-transform: translate3d(-250px, 0, 0); - transform: translate3d(-250px, 0, 0); -} - -.pushy-open-left #container, .pushy-open-left .push { - -webkit-transform: translate3d(250px, 0, 0); - -ms-transform: translate3d(250px, 0, 0); - transform: translate3d(250px, 0, 0); -} - -.pushy-right { - -webkit-transform: translate3d(250px, 0, 0); - -ms-transform: translate3d(250px, 0, 0); - transform: translate3d(250px, 0, 0); -} - -.pushy-open-right #container, .pushy-open-right .push { - -webkit-transform: translate3d(-250px, 0, 0); - -ms-transform: translate3d(-250px, 0, 0); - transform: translate3d(-250px, 0, 0); -} - -.pushy-open-left .pushy, .pushy-open-right .pushy { - -webkit-transform: translate3d(0, 0, 0); - -ms-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} - -.pushy-open-left .pushy-content, .pushy-open-right .pushy-content { - visibility: visible; -} - - -/* Menu Transitions */ - -#container, .pushy, .push { - transition: transform 0.2s cubic-bezier(0.16, 0.68, 0.43, 0.99); -} - -.pushy-content { - transition: visibility 0.2s cubic-bezier(0.16, 0.68, 0.43, 0.99); -} - - -/* Site Overlay */ - -.site-overlay { - display: none; -} - -.pushy-open-left .site-overlay, .pushy-open-right .site-overlay { - display: block; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 9998; - background-color: rgba(0, 0, 0, 0.5); - -webkit-animation: fade 500ms; - animation: fade 500ms; -} - -@keyframes fade { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} - -@-webkit-keyframes fade { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} - - -/* Submenu Appearance */ - - -/* .pushy-submenu { */ - - -/* Submenu Buttons */ - - -/* Submenu Icon */ - - -/* } */ - - -/* .pushy-submenu ul { - padding-left: 15px; - transition: max-height 0.2s ease-in-out, visibility 0.2s ease-in-out; -} - -.pushy-submenu ul .pushy-link { - transition: opacity 0.2s ease-in-out; -} - -.pushy-submenu button { - width: 100%; - color: #b3b3b1; - padding: 15px 30px; - text-align: left; - background: transparent; - border: 0; -} - -.pushy-submenu button:hover { - color: #FFF; -} - -.pushy-submenu>a, .pushy-submenu>button { - position: relative; -} - -.pushy-submenu>a::after, .pushy-submenu>button::after { - content: ''; - display: block; - height: 11px; - width: 8px; - position: absolute; - top: 50%; - right: 15px; - background: url("https://cdnjs.cloudflare.com/ajax/libs/pushy/1.1.0/img/arrow.svg") no-repeat; - -webkit-transform: translateY(-50%); - -ms-transform: translateY(-50%); - transform: translateY(-50%); - transition: transform 0.2s; -} */ - - -/* Submenu Movement */ - - -/* -.pushy-submenu-closed ul { - max-height: 0; - overflow: hidden; - visibility: hidden; -} - -.pushy-submenu-closed .pushy-link { - opacity: 0; -} - -.pushy-submenu-open { - /* Submenu Icon */ - - -/*}*/ - - -/* -.pushy-submenu-open ul { - max-height: 1000px; - visibility: visible; -} - -.pushy-submenu-open .pushy-link { - opacity: 1; -} - -.pushy-submenu-open a::after, .pushy-submenu-open button::after { - -webkit-transform: translateY(-50%) rotate(90deg); - -ms-transform: translateY(-50%) rotate(90deg); - transform: translateY(-50%) rotate(90deg); -}*/ - - -/************************************** - LOG PAGE SECTION CSS -***************************************/ - -.logs-div { - text-align: left; - vertical-align: middle; - padding: 0, 0; -} - -.log-line { - display: inline-block; - padding-bottom: 8px; - vertical-align: middle; -} - -.log-time { - font-weight: bold; - vertical-align: middle; -} - -.log-type { - display: inline-block; - padding: .2em .6em .3em; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: middle; - border-radius: .25em; - min-width: 44px; - font-size: 0.75em; -} - -.log-source { - border-radius: 0.3em; - border-color: gray; - border-style: solid; - border-width: 1px; - padding: 2px; - font-style: italic; - vertical-align: middle; -} - -.log-msg { - vertical-align: middle; -} - -.defsrc-bg { - color: gray; - background-color: white; - font-size: 0.9em; -} - -.mansrc-bg { - color: #6b6b6b; - background-color: transparent; - font-size: 0.9em; -} - -.autosrc-bg { - color: #6b6b6b; - background-color: lightgray; - font-size: 0.9em; -} - -.camsrc-bg { - color: #6b6b6b; - background-color: lightblue; - font-size: 0.9em; -} - -.protsrc-bg { - color: #6b6b6b; - background-color: lightorange; - font-size: 0.9em; -} - -.pressrc-bg { - color: #6b6b6b; - background-color: lightyellow; - font-size: 0.9em; -} - -.weatsrc-bg { - color: #6b6b6b; - background-color: lightpurple; - font-size: 0.9em; -} - -.tstatsrc-bg { - color: #6b6b6b; - background-color: lightgreen; - font-size: 0.9em; -} - -.centerText { - text-align: center; -} - -.mapDataFmt {} - - -/************************************** - BACK TO TOP CSS BUTTON -***************************************/ - -#scrollTopBtn { - display: none; - position: fixed; - bottom: 20px; - right: 30px; - z-index: 99; - border: none; - outline: none; - background-color: gray; - color: white; - cursor: pointer; - padding: 15px; - border-radius: 10px; -} - -#scrollTopBtn:hover { - background-color: #3174AE; -} - -.export-pdf-btn { - color: white; - width: auto; - height: auto; - max-width: 90px; - max-height: 40px; - font-size: 1.0em; - border-radius: 0.4em; - background-color: transparent; - border-color: white; - border-style: solid; - border-width: 1px; -} - -.panel-title-text { - padding-top: 0.5em; - font-size: 24px; -} - -.subpanel-title-text { - font-size: 18px; -} - -.panelHeadTxt { - font-size: 25px; -} - -.pnl-head-title { - font-size: 2.0em; -} - -@media (min-width: 800px) { - .pnl-head-title { - padding: 3px 0; - } -} - -@media (min-width: 600px) { - .pnl-head-title { - padding: 5px 0; - } -} - -.title-text { - font-size: 2.0em; -} - -/************************************** - PRE CODE CSS -***************************************/ -pre { - overflow-x: auto; - overflow-y: auto; -} - -/************************************** - NAV BAR CSS -***************************************/ - -.navMenu { - text-align: left; -} - -.nav-home-btn { - padding: 20px 10px 0 10px; - font-size: 22px; -} - -.nav-menu { - padding: 12px; -} - -.nav-menu li { - border-bottom: solid 1px rgba(102, 102, 102, 0.3); - margin-left: 5px; - margin-right: 5px; - font-size: 14px; - padding: 12px; -} - -.nav-menu li a { - color: white; - text-decoration: none; -} - -.nav-menu li a:hover { - color: tomato; - text-decoration: none; -} - -.nav-menu li .sub-nav { - border-bottom: 0px; - padding: 4px; -} - -.nav-menu a .caret { - width: 0; - height: 0; - display: inline-block; - vertical-align: top; - border-top: 4px solid #4f5963; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; - margin-top: 8px; -} - -.nav-menu a:hover .caret { - border-top-color: #4f5963; -} - -.nav-menu li.open>a>.caret { - border-top: none; - border-bottom: 4px solid #4f5963; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} - -.nav-menu li.open>a:hover>.caret { - border-bottom-color: #4f5963; -} - -.icon:before { - font-family: 'FontAwesome'; - font-style: normal; - font-variant: normal; - font-weight: normal; - line-height: 1; - text-transform: none; - content: '\f105'; -} - -.nav-menu li>a>span.icon { - float: right; - margin: 0.1em 1.7em -0.1em 0; - opacity: 0; - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -.nav-menu li>a:hover>span.icon { - float: right; - margin: 0.1em 0.8em -0.1em 0; - opacity: 1; -} - -.menu-btn:focus { - outline: none; -} - -.nav-cont-bord-div { - padding: 15px 15px 25px 15px; -} - -.nav-cont-div { - padding: 10px; - border-radius: 0.6em; - background-color: #333333; - border: solid lightgray 1px; - -moz-box-shadow: 0px 5px 1px #ccc; - -webkit-box-shadow: 0px 1px 1px #ccc; - box-shadow: 0px 1px 1px #ccc; -} - -.nav-key-item { - font-weight: bold; - text-decoration: underline; - list-style: none; - font-size: 1.0em; -} - -.nav-subkey-item { - font-weight: normal; - list-style: none; -} - -.nav-subkey-item:before { - color: white; - content: "▶"; - padding-right: 8px; -} - - -/* Menu Appearance */ - -.pushy { - position: fixed; - width: 250px; - height: 100%; - top: 0; - z-index: 9999; - background: #191918; - overflow: auto; - -webkit-overflow-scrolling: touch; - /* enables momentum scrolling in iOS overflow elements */ -} - - -/* -.pushy a { - display: block; - color: #b3b3b1; - padding: 15px 30px; - text-decoration: none; -} - -.pushy a:hover { - color: #FFF; -} - -.pushy ul:first-child { - margin-top: 10px; -} -*/ - -.pushy.pushy-left { - left: 0; -} - -.pushy.pushy-right { - right: 0; -} - - -/*.pushy-content { - visibility: hidden; -}*/ - - -/* Menu Movement */ - -.pushy-left { - -webkit-transform: translate3d(-250px, 0, 0); - -ms-transform: translate3d(-250px, 0, 0); - transform: translate3d(-250px, 0, 0); -} - -.pushy-open-left #container, .pushy-open-left .push { - -webkit-transform: translate3d(250px, 0, 0); - -ms-transform: translate3d(250px, 0, 0); - transform: translate3d(250px, 0, 0); -} - -.pushy-right { - -webkit-transform: translate3d(250px, 0, 0); - -ms-transform: translate3d(250px, 0, 0); - transform: translate3d(250px, 0, 0); -} - -.pushy-open-right #container, .pushy-open-right .push { - -webkit-transform: translate3d(-250px, 0, 0); - -ms-transform: translate3d(-250px, 0, 0); - transform: translate3d(-250px, 0, 0); -} - -.pushy-open-left .pushy, .pushy-open-right .pushy { - -webkit-transform: translate3d(0, 0, 0); - -ms-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} - -.pushy-open-left .pushy-content, .pushy-open-right .pushy-content { - visibility: visible; -} - - -/* Menu Transitions */ - -#container, .pushy, .push { - transition: transform 0.2s cubic-bezier(0.16, 0.68, 0.43, 0.99); -} - -.pushy-content { - transition: visibility 0.2s cubic-bezier(0.16, 0.68, 0.43, 0.99); -} - - -/* Site Overlay */ - -.site-overlay { - display: none; -} - -.pushy-open-left .site-overlay, .pushy-open-right .site-overlay { - display: block; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 9998; - background-color: rgba(0, 0, 0, 0.5); - -webkit-animation: fade 500ms; - animation: fade 500ms; -} - -@keyframes fade { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} - -@-webkit-keyframes fade { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } -} - - -/* Submenu Appearance */ - - -/* .pushy-submenu { */ - - -/* Submenu Buttons */ - - -/* Submenu Icon */ - - -/* } */ - - -/* .pushy-submenu ul { - padding-left: 15px; - transition: max-height 0.2s ease-in-out, visibility 0.2s ease-in-out; -} - -.pushy-submenu ul .pushy-link { - transition: opacity 0.2s ease-in-out; -} - -.pushy-submenu button { - width: 100%; - color: #b3b3b1; - padding: 15px 30px; - text-align: left; - background: transparent; - border: 0; -} - -.pushy-submenu button:hover { - color: #FFF; -} - -.pushy-submenu>a, .pushy-submenu>button { - position: relative; -} - -.pushy-submenu>a::after, .pushy-submenu>button::after { - content: ''; - display: block; - height: 11px; - width: 8px; - position: absolute; - top: 50%; - right: 15px; - background: url("https://cdnjs.cloudflare.com/ajax/libs/pushy/1.1.0/img/arrow.svg") no-repeat; - -webkit-transform: translateY(-50%); - -ms-transform: translateY(-50%); - transform: translateY(-50%); - transition: transform 0.2s; -} */ - - -/* Submenu Movement */ - - -/* -.pushy-submenu-closed ul { - max-height: 0; - overflow: hidden; - visibility: hidden; -} - -.pushy-submenu-closed .pushy-link { - opacity: 0; -} - -.pushy-submenu-open { - /* Submenu Icon */ - - -/*}*/ - - -/* -.pushy-submenu-open ul { - max-height: 1000px; - visibility: visible; -} - -.pushy-submenu-open .pushy-link { - opacity: 1; -} - -.pushy-submenu-open a::after, .pushy-submenu-open button::after { - -webkit-transform: translateY(-50%) rotate(90deg); - -ms-transform: translateY(-50%) rotate(90deg); - transform: translateY(-50%) rotate(90deg); -}*/ - - -/************************************** - LOG PAGE SECTION CSS -***************************************/ - -.logs-div { - text-align: left; - padding: 0, 0; -} - -.label { - display: inline; - padding: .2em .6em .3em; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} - -.logSrcFmt { - border-radius: 0.3em; - border-color: gray; - border-style: solid; - border-width: 1px; - padding: 2px; - font-style: italic; -} - -.defsrc-bg { - color: gray; - background-color: lightgray; -} - -.mansrc-bg { - color: gray; - background-color: lightgray; -} - -.autosrc-bg { - color: gray; - background-color: lightgray; -} - -.camsrc-bg { - color: gray; - background-color: lightgray; -} - -.protsrc-bg { - color: gray; - background-color: lightgray; -} - -.pressrc-bg { - color: gray; - background-color: lightgray; -} - -.weatsrc-bg { - color: gray; - background-color: lightgray; -} - -.tstatsrc-bg { - color: gray; - background-color: lightgray; -} - -.centerText { - text-align: center; -} - -.logEvtDt { - font-weight: bold; -} - -.mapDataFmt {} - - -/************************************** - BACK TO TOP CSS BUTTON -***************************************/ - -#scrollTopBtn { - display: none; - position: fixed; - bottom: 20px; - right: 30px; - z-index: 99; - border: none; - outline: none; - background-color: gray; - color: white; - cursor: pointer; - padding: 15px; - border-radius: 10px; +.hamburger-box { + width: 27px; + height: 24px; } -#scrollTopBtn:hover { - background-color: #3174AE; +.hamburger-inner, .hamburger-inner:after, .hamburger-inner:before { + width: 27px; + height: 4px; } .export-pdf-btn { diff --git a/Documents/css/diagpages.min.css b/Documents/css/diagpages.min.css index c327138b2..54165d8fd 100644 --- a/Documents/css/diagpages.min.css +++ b/Documents/css/diagpages.min.css @@ -1 +1 @@ -html,body{position:relative;height:100%;min-height:100%;min-width:375px}.container{width:100%;margin:auto}#top-hdr{height:auto;min-width:375px}.in-middle{vertical-align:middle}.left-head-col{padding:1.2em 0 0 20px}.right-head-col{padding:2.1em 40px 0 0}.links{padding:10px;font-size:18px}.logoIcn{width:1.7em;height:auto;max-width:48px;max-height:48px}.refresh-btn{color:black;width:auto;height:auto;max-width:90px;max-height:40px;font-size:1.0em;border-radius:.4em;background-color:white;border-color:gray;border-style:solid;border-width:1px}#rfrshBtn:after{content:' Refresh'}@media screen and (max-width:520px){#rfrshBtn:after{content:''}#rfrshBtn{font-size:1.1em}}.export-pdf-btn{color:white;width:auto;height:auto;max-width:90px;max-height:40px;font-size:1.0em;border-radius:.4em;background-color:transparent;border-color:white;border-style:solid;border-width:1px;display:none}.panel-title-text{padding-top:.5em;font-size:24px}.subpanel-title-text{font-size:18px}.panelHeadTxt{font-size:25px}.pnl-head-title{font-size:2.0em}@media(min-width:800px){.pnl-head-title{padding:3px 0}}@media(min-width:600px){.pnl-head-title{padding:5px 0}}.title-text{font-size:2.0em}pre{overflow-x:auto;overflow-y:auto}.navMenu{text-align:left}.nav-home-btn{padding:20px 10px 0 10px;font-size:22px}.nav-menu{padding:12px}.nav-menu li{border-bottom:solid 1px rgba(102,102,102,0.3);margin-left:5px;margin-right:5px;font-size:14px;padding:12px}.nav-menu li a{color:white;text-decoration:none}.nav-menu li a:hover{color:tomato;text-decoration:none}.nav-menu li .sub-nav{border-bottom:0;padding:4px}.nav-menu a .caret{width:0;height:0;display:inline-block;vertical-align:top;border-top:4px solid #4f5963;border-right:4px solid transparent;border-left:4px solid transparent;content:"";margin-top:8px}.nav-menu a:hover .caret{border-top-color:#4f5963}.nav-menu li.open>a>.caret{border-top:0;border-bottom:4px solid #4f5963;border-right:4px solid transparent;border-left:4px solid transparent}.nav-menu li.open>a:hover>.caret{border-bottom-color:#4f5963}.icon:before{font-family:'FontAwesome';font-style:normal;font-variant:normal;font-weight:normal;line-height:1;text-transform:none;content:'\f105'}.nav-menu li>a>span.icon{float:right;margin:.1em 1.7em -0.1em 0;opacity:0;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.nav-menu li>a:hover>span.icon{float:right;margin:.1em .8em -0.1em 0;opacity:1}.menu-btn:focus{outline:0}.nav-cont-bord-div{padding:15px 15px 25px 15px}.nav-cont-div{padding:10px;border-radius:.6em;background-color:#333;border:solid lightgray 1px;-moz-box-shadow:0 5px 1px #ccc;-webkit-box-shadow:0 1px 1px #ccc;box-shadow:0 1px 1px #ccc}.nav-key-item{font-weight:bold;text-decoration:underline;list-style:none;font-size:1.0em}.nav-subkey-item{font-weight:normal;list-style:none}.nav-subkey-item:before{color:white;content:"▶";padding-right:8px}.pushy{position:fixed;width:250px;height:100%;top:0;z-index:9999;background:#191918;overflow:auto;-webkit-overflow-scrolling:touch}.pushy.pushy-left{left:0}.pushy.pushy-right{right:0}.pushy-left{-webkit-transform:translate3d(-250px,0,0);-ms-transform:translate3d(-250px,0,0);transform:translate3d(-250px,0,0)}.pushy-open-left #container,.pushy-open-left .push{-webkit-transform:translate3d(250px,0,0);-ms-transform:translate3d(250px,0,0);transform:translate3d(250px,0,0)}.pushy-right{-webkit-transform:translate3d(250px,0,0);-ms-transform:translate3d(250px,0,0);transform:translate3d(250px,0,0)}.pushy-open-right #container,.pushy-open-right .push{-webkit-transform:translate3d(-250px,0,0);-ms-transform:translate3d(-250px,0,0);transform:translate3d(-250px,0,0)}.pushy-open-left .pushy,.pushy-open-right .pushy{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.pushy-open-left .pushy-content,.pushy-open-right .pushy-content{visibility:visible}#container,.pushy,.push{transition:transform .2s cubic-bezier(0.16,0.68,0.43,0.99)}.pushy-content{transition:visibility .2s cubic-bezier(0.16,0.68,0.43,0.99)}.site-overlay{display:none}.pushy-open-left .site-overlay,.pushy-open-right .site-overlay{display:block;position:fixed;top:0;right:0;bottom:0;left:0;z-index:9998;background-color:rgba(0,0,0,0.5);-webkit-animation:fade 500ms;animation:fade 500ms}@keyframes fade{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fade{0%{opacity:0}100%{opacity:1}}.logs-div{text-align:left;vertical-align:middle;padding:0,0}.log-line{display:inline-block;padding-bottom:8px;vertical-align:middle}.log-time{font-weight:bold;vertical-align:middle}.log-type{display:inline-block;padding:.2em .6em .3em;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;border-radius:.25em;min-width:44px;font-size:.75em}.log-source{border-radius:.3em;border-color:gray;border-style:solid;border-width:1px;padding:2px;font-style:italic;vertical-align:middle}.log-msg{vertical-align:middle}.defsrc-bg{color:gray;background-color:white;font-size:.9em}.mansrc-bg{color:#6b6b6b;background-color:transparent;font-size:.9em}.autosrc-bg{color:#6b6b6b;background-color:lightgray;font-size:.9em}.camsrc-bg{color:#6b6b6b;background-color:lightblue;font-size:.9em}.protsrc-bg{color:#6b6b6b;background-color:lightorange;font-size:.9em}.pressrc-bg{color:#6b6b6b;background-color:lightyellow;font-size:.9em}.weatsrc-bg{color:#6b6b6b;background-color:lightpurple;font-size:.9em}.tstatsrc-bg{color:#6b6b6b;background-color:lightgreen;font-size:.9em}.centerText{text-align:center}#scrollTopBtn{display:none;position:fixed;bottom:20px;right:30px;z-index:99;border:0;outline:0;background-color:gray;color:white;cursor:pointer;padding:15px;border-radius:10px}#scrollTopBtn:hover{background-color:#3174ae} \ No newline at end of file +html,body{position:relative;height:100%;min-height:100%;min-width:375px}.container{width:100%;margin:auto}#top-hdr{height:auto;min-width:375px}.in-middle{vertical-align:middle}.left-head-col{padding:1.2em 0 0 20px}.right-head-col{padding:2.1em 40px 0 0}.links{padding:10px;font-size:18px}.logoIcn{width:1.7em;height:auto;max-width:48px;max-height:48px}.refresh-btn{color:black;width:auto;height:auto;max-width:90px;max-height:40px;font-size:1.0em;border-radius:.4em;background-color:white;border-color:gray;border-style:solid;border-width:1px}#rfrshBtn:after{content:' Refresh'}@media screen and (max-width:520px){#rfrshBtn:after{content:''}#rfrshBtn{font-size:1.1em}}.hamburger-box{width:27px;height:24px}.hamburger-inner,.hamburger-inner:after,.hamburger-inner:before{width:27px;height:4px}.export-pdf-btn{color:white;width:auto;height:auto;max-width:90px;max-height:40px;font-size:1.0em;border-radius:.4em;background-color:transparent;border-color:white;border-style:solid;border-width:1px;display:none}.panel-title-text{padding-top:.5em;font-size:24px}.subpanel-title-text{font-size:18px}.panelHeadTxt{font-size:25px}.pnl-head-title{font-size:2.0em}@media(min-width:800px){.pnl-head-title{padding:3px 0}}@media(min-width:600px){.pnl-head-title{padding:5px 0}}.title-text{font-size:2.0em}pre{overflow-x:auto;overflow-y:auto}.navMenu{text-align:left}.nav-home-btn{padding:20px 10px 0 10px;font-size:22px}.nav-menu{padding:12px}.nav-menu li{border-bottom:solid 1px rgba(102,102,102,0.3);margin-left:5px;margin-right:5px;font-size:14px;padding:12px}.nav-menu li a{color:white;text-decoration:none}.nav-menu li a:hover{color:tomato;text-decoration:none}.nav-menu li .sub-nav{border-bottom:0;padding:4px}.nav-menu a .caret{width:0;height:0;display:inline-block;vertical-align:top;border-top:4px solid #4f5963;border-right:4px solid transparent;border-left:4px solid transparent;content:"";margin-top:8px}.nav-menu a:hover .caret{border-top-color:#4f5963}.nav-menu li.open>a>.caret{border-top:0;border-bottom:4px solid #4f5963;border-right:4px solid transparent;border-left:4px solid transparent}.nav-menu li.open>a:hover>.caret{border-bottom-color:#4f5963}.icon:before{font-family:'FontAwesome';font-style:normal;font-variant:normal;font-weight:normal;line-height:1;text-transform:none;content:'\f105'}.nav-menu li>a>span.icon{float:right;margin:.1em 1.7em -0.1em 0;opacity:0;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.nav-menu li>a:hover>span.icon{float:right;margin:.1em .8em -0.1em 0;opacity:1}.menu-btn:focus{outline:0}.nav-cont-bord-div{padding:15px 15px 25px 15px}.nav-cont-div{padding:10px;border-radius:.6em;background-color:#333;border:solid lightgray 1px;-moz-box-shadow:0 5px 1px #ccc;-webkit-box-shadow:0 1px 1px #ccc;box-shadow:0 1px 1px #ccc}.nav-key-item{font-weight:bold;text-decoration:underline;list-style:none;font-size:1.0em}.nav-subkey-item{font-weight:normal;list-style:none}.nav-subkey-item:before{color:white;content:"▶";padding-right:8px}.pushy{position:fixed;width:250px;height:100%;top:0;z-index:9999;background:#191918;overflow:auto;-webkit-overflow-scrolling:touch}.pushy.pushy-left{left:0}.pushy.pushy-right{right:0}.pushy-left{-webkit-transform:translate3d(-250px,0,0);-ms-transform:translate3d(-250px,0,0);transform:translate3d(-250px,0,0)}.pushy-open-left #container,.pushy-open-left .push{-webkit-transform:translate3d(250px,0,0);-ms-transform:translate3d(250px,0,0);transform:translate3d(250px,0,0)}.pushy-right{-webkit-transform:translate3d(250px,0,0);-ms-transform:translate3d(250px,0,0);transform:translate3d(250px,0,0)}.pushy-open-right #container,.pushy-open-right .push{-webkit-transform:translate3d(-250px,0,0);-ms-transform:translate3d(-250px,0,0);transform:translate3d(-250px,0,0)}.pushy-open-left .pushy,.pushy-open-right .pushy{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.pushy-open-left .pushy-content,.pushy-open-right .pushy-content{visibility:visible}#container,.pushy,.push{transition:transform .2s cubic-bezier(0.16,0.68,0.43,0.99)}.pushy-content{transition:visibility .2s cubic-bezier(0.16,0.68,0.43,0.99)}.site-overlay{display:none}.pushy-open-left .site-overlay,.pushy-open-right .site-overlay{display:block;position:fixed;top:0;right:0;bottom:0;left:0;z-index:9998;background-color:rgba(0,0,0,0.5);-webkit-animation:fade 500ms;animation:fade 500ms}@keyframes fade{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fade{0%{opacity:0}100%{opacity:1}}.logs-div{text-align:left;vertical-align:middle;padding:0,0}.log-line{display:inline-block;padding-bottom:8px;vertical-align:middle}.log-time{font-weight:bold;vertical-align:middle}.log-type{display:inline-block;padding:.2em .6em .3em;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;border-radius:.25em;min-width:44px;font-size:.75em}.log-source{border-radius:.3em;border-color:gray;border-style:solid;border-width:1px;padding:2px;font-style:italic;vertical-align:middle}.log-msg{vertical-align:middle}.defsrc-bg{color:gray;background-color:white;font-size:.9em}.mansrc-bg{color:#6b6b6b;background-color:transparent;font-size:.9em}.autosrc-bg{color:#6b6b6b;background-color:lightgray;font-size:.9em}.camsrc-bg{color:#6b6b6b;background-color:lightblue;font-size:.9em}.protsrc-bg{color:#6b6b6b;background-color:lightorange;font-size:.9em}.pressrc-bg{color:#6b6b6b;background-color:lightyellow;font-size:.9em}.weatsrc-bg{color:#6b6b6b;background-color:lightpurple;font-size:.9em}.tstatsrc-bg{color:#6b6b6b;background-color:lightgreen;font-size:.9em}.centerText{text-align:center}#scrollTopBtn{display:none;position:fixed;bottom:20px;right:30px;z-index:99;border:0;outline:0;background-color:gray;color:white;cursor:pointer;padding:15px;border-radius:10px}#scrollTopBtn:hover{background-color:#3174ae} \ No newline at end of file diff --git a/Documents/css/diagpages_new.css b/Documents/css/diagpages_new.css index 84ed193b3..9c81bb201 100644 --- a/Documents/css/diagpages_new.css +++ b/Documents/css/diagpages_new.css @@ -1,4 +1,5 @@ -html, body { +html, +body { position: relative; height: 100%; min-height: 100%; @@ -81,6 +82,7 @@ html, body { /* padding-top: 0.5em; */ font-size: 1.2em; } + .subpanel-title-text { /* padding-top: 0.5em; */ font-size: 1em; @@ -315,7 +317,8 @@ pre { transform: translate3d(-250px, 0, 0); } -.pushy-open-left #container, .pushy-open-left .push { +.pushy-open-left #container, +.pushy-open-left .push { -webkit-transform: translate3d(250px, 0, 0); -ms-transform: translate3d(250px, 0, 0); transform: translate3d(250px, 0, 0); @@ -327,26 +330,31 @@ pre { transform: translate3d(250px, 0, 0); } -.pushy-open-right #container, .pushy-open-right .push { +.pushy-open-right #container, +.pushy-open-right .push { -webkit-transform: translate3d(-250px, 0, 0); -ms-transform: translate3d(-250px, 0, 0); transform: translate3d(-250px, 0, 0); } -.pushy-open-left .pushy, .pushy-open-right .pushy { +.pushy-open-left .pushy, +.pushy-open-right .pushy { -webkit-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } -.pushy-open-left .pushy-content, .pushy-open-right .pushy-content { +.pushy-open-left .pushy-content, +.pushy-open-right .pushy-content { visibility: visible; } /* Menu Transitions */ -#container, .pushy, .push { +#container, +.pushy, +.push { transition: transform 0.2s cubic-bezier(0.16, 0.68, 0.43, 0.99); } @@ -361,7 +369,8 @@ pre { display: none; } -.pushy-open-left .site-overlay, .pushy-open-right .site-overlay { +.pushy-open-left .site-overlay, +.pushy-open-right .site-overlay { display: block; position: fixed; top: 0; @@ -611,30 +620,40 @@ pre { background-color: #3174AE; } + /************************************** DEVICE TILE CSS ***************************************/ -.vex.vex-theme-default .vex-content { width: 50%; padding: 3px; } +.vex.vex-theme-default .vex-content { + width: 50%; + padding: 3px; +} + .device table { border: none; border-radius: 3px; - width:100%; + width: 100%; -webkit-border-radius: 3px; -moz-border-radius: 3px; } -.device h1, h2, h3, h4, h5, h6 { - padding:20px; - margin:4px; +.device h1, +h2, +h3, +h4, +h5, +h6 { + padding: 20px; + margin: 4px; } .topBorder { - border-top: 2px solid #00a1db; + border-top: 2px solid #00a1db; } .bottomBorder { - border-bottom: 2px solid #808080; + border-bottom: 2px solid #808080; } .device { @@ -644,133 +663,207 @@ pre { } .device h1 { - font-size: 6vw; - width: 100%; - text-align: center; - font-weight: normal; + font-size: 6vw; + width: 100%; + text-align: center; + font-weight: normal; } .device h2 { - font-size: 9vw; - text-align: center; - margin-left: auto; - margin-right: auto; - font-weight: normal; + font-size: 9vw; + text-align: center; + margin-left: auto; + margin-right: auto; + font-weight: normal; } - -.device h3, h3 a { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #B74C4C; - color: #f5f5f5; +.device h3, +h3 a { + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #B74C4C; + color: #f5f5f5; } .device h4 { - font-size: 4vw; - font-weight: bold; - text-align: center; - background: #00a1db; - color: #f5f5f5; + font-size: 4vw; + font-weight: bold; + text-align: center; + background: #00a1db; + color: #f5f5f5; } .centerText { - text-align: center; + text-align: center; } .device hr { - background: #00a1db; - width: 100%; - height: 1px; + background: #00a1db; + width: 100%; + height: 1px; } -.device th, td { - box-shadow: inset 0 0px rgba(0, 0, 0, 0.25), inset 0 0px rgba(0, 0, 0, 0.25); - padding: 4px; + +.device th, +td { + box-shadow: inset 0 0px rgba(0, 0, 0, 0.25), inset 0 0px rgba(0, 0, 0, 0.25); + padding: 4px; } .device th { - -webkit-font-smoothing: antialiased; - color: #f5f5f5; - text-shadow: 0 0 1px rgba(0, 0, 0, 0.1); - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - background: #00a1db; + -webkit-font-smoothing: antialiased; + color: #f5f5f5; + text-shadow: 0 0 1px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + background: #00a1db; } .devInfo th { - font-size: 3.8vw; + font-size: 3.8vw; } + .devInfoTile th { - font-size: 2.0vw; + font-size: 2.0vw; } + .devInfoTile h4 { - font-size: 1.5vw; + font-size: 1.5vw; } .device td { - color: grey; - text-shadow: 0 0 1px rgba(255, 255, 255, 0.1); - text-align: center; + color: grey; + text-shadow: 0 0 1px rgba(255, 255, 255, 0.1); + text-align: center; } .device tr { - -webkit-transition: background 0.3s, box-shadow 0.3s; - -moz-transition: background 0.3s, box-shadow 0.3s; - transition: background 0.3s, box-shadow 0.3s; + -webkit-transition: background 0.3s, box-shadow 0.3s; + -moz-transition: background 0.3s, box-shadow 0.3s; + transition: background 0.3s, box-shadow 0.3s; } + .column, .columns { - width: 100%; - float: left; - box-sizing: border-box; + width: 100%; + float: left; + box-sizing: border-box; } .one.column, -.one.columns { width: 4.66666666667%; } -.two.columns { width: 13.3333333333%; } -.three.columns { width: 22%; } -.four.columns { width: 32.6666666667%; } -.five.columns { width: 39.3333333333%; } -.six.columns { width: 48%; } -.seven.columns { width: 56.6666666667%; } -.eight.columns { width: 65.3333333333%; } -.nine.columns { width: 74.0%; } -.ten.columns { width: 82.6666666667%; } -.eleven.columns { width: 91.3333333333%; } -.twelve.columns { width: 100%; margin-left: 0; } +.one.columns { + width: 4.66666666667%; +} + +.two.columns { + width: 13.3333333333%; +} + +.three.columns { + width: 22%; +} + +.four.columns { + width: 32.6666666667%; +} + +.five.columns { + width: 39.3333333333%; +} + +.six.columns { + width: 48%; +} + +.seven.columns { + width: 56.6666666667%; +} + +.eight.columns { + width: 65.3333333333%; +} + +.nine.columns { + width: 74.0%; +} + +.ten.columns { + width: 82.6666666667%; +} + +.eleven.columns { + width: 91.3333333333%; +} + +.twelve.columns { + width: 100%; + margin-left: 0; +} /* Offsets */ + .offset-by-one.column, -.offset-by-one.columns { margin-left: 8.66666666667%; } +.offset-by-one.columns { + margin-left: 8.66666666667%; +} + .offset-by-two.column, -.offset-by-two.columns { margin-left: 17.3333333333%; } +.offset-by-two.columns { + margin-left: 17.3333333333%; +} + .offset-by-three.column, -.offset-by-three.columns { margin-left: 26%; } +.offset-by-three.columns { + margin-left: 26%; +} + .offset-by-four.column, -.offset-by-four.columns { margin-left: 34.6666666667%; } +.offset-by-four.columns { + margin-left: 34.6666666667%; +} + .offset-by-five.column, -.offset-by-five.columns { margin-left: 43.3333333333%; } +.offset-by-five.columns { + margin-left: 43.3333333333%; +} + .offset-by-six.column, -.offset-by-six.columns { margin-left: 52%; } +.offset-by-six.columns { + margin-left: 52%; +} + .offset-by-seven.column, -.offset-by-seven.columns { margin-left: 60.6666666667%; } +.offset-by-seven.columns { + margin-left: 60.6666666667%; +} + .offset-by-eight.column, -.offset-by-eight.columns { margin-left: 69.3333333333%; } +.offset-by-eight.columns { + margin-left: 69.3333333333%; +} + .offset-by-nine.column, -.offset-by-nine.columns { margin-left: 78.0%; } +.offset-by-nine.columns { + margin-left: 78.0%; +} + .offset-by-ten.column, -.offset-by-ten.columns { margin-left: 86.6666666667%; } +.offset-by-ten.columns { + margin-left: 86.6666666667%; +} + .offset-by-eleven.column, -.offset-by-eleven.columns { margin-left: 95.3333333333%; } +.offset-by-eleven.columns { + margin-left: 95.3333333333%; +} .dateTimeText { - font-size: 3.4vw; + font-size: 3.4vw; } .dateTimeTextTile { - font-size: 1.5vw; + font-size: 1.5vw; } .dateTimeTextSmall { @@ -778,92 +871,94 @@ pre { } .battImg { - width:30px; height:15px; + width: 30px; + height: 15px; } .leafImg { - width: 25px; - height: 25px; + width: 25px; + height: 25px; } -.red{ - background-color:#db3a00; + +.red { + background-color: #db3a00; } -.yellow{ - background-color:#dba800; +.yellow { + background-color: #dba800; } .redAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #B74C4C; - color: #f5f5f5; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #B74C4C; + color: #f5f5f5; + padding: 8px 0px; } .brightRedAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #ff3b19; - color: #f5f5f5; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #ff3b19; + color: #f5f5f5; + padding: 8px 0px; } .greenAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #00ff00; - -webkit-text-stroke: 1.0px #000000; - -webkit-text-fill-color: #FFFFFF; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #00ff00; + -webkit-text-stroke: 1.0px #000000; + -webkit-text-fill-color: #FFFFFF; + padding: 8px 0px; } .androidAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #6f786f; - -webkit-text-stroke: 1.0px #000000; - -webkit-text-fill-color: #FFFFFF; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #6f786f; + -webkit-text-stroke: 1.0px #000000; + -webkit-text-fill-color: #FFFFFF; + padding: 8px 0px; } .orangeAlertBanner { - font-size: 6vw; - font-weight: bold; - text-align: center; - background: #ffae19; - color: #f5f5f5; - padding: 8px 0px; + font-size: 6vw; + font-weight: bold; + text-align: center; + background: #ffae19; + color: #f5f5f5; + padding: 8px 0px; } .blueTitle { - font-size: 4vw; - font-weight: bold; - text-align: center; - background: #00a1db; - color: #f5f5f5; + font-size: 4vw; + font-weight: bold; + text-align: center; + background: #00a1db; + color: #f5f5f5; } .alertModalTitle { - font-size: 22px; - font-weight: bold; - text-align: center; - background: transparent; - color: black; + font-size: 22px; + font-weight: bold; + text-align: center; + background: transparent; + color: black; } .sched h3 { - font-size: 4.6vw; - background: #00a1db; + font-size: 4.6vw; + background: #00a1db; } .sched h4 { - font-size: 3.8vw; - background: #00a1db; + font-size: 3.8vw; + background: #00a1db; } .sched col { @@ -873,19 +968,24 @@ pre { .slideFooterMsg { font-size: 3.0vw; padding: 20px; - margin:1em auto; + margin: 1em auto; } -.slideFooterMsgTile { +.slideFooterMsg { font-size: 1.8vw; padding: 20px; - margin:1em auto; + margin: 1em auto; + text-decoration: underline; +} + +.slideFooterTextTile { + font-size: 1.8vw; + margin: 1em auto; text-decoration: underline; } .pageFooterBtn { padding: 10px; - horizontal-align: center; text-align: center; } @@ -904,10 +1004,43 @@ pre { color: gray; } +.slideFooterBtn { + font-size: 1rem; + text-align: center; + padding: 0; +} + +.slideFooterText { + font-size: 3.0vw; + margin: 1em auto; + padding: 0; + text-decoration: underline; +} + +.pageFooterCls { + text-align: center; +} + .swiper-container { width: 95%; min-height: 300px; - padding: 10px; + padding: 0 10px !important; +} + +.swiper-pagination-bullet { + width: 20px; + height: 20px; + text-align: center; + line-height: 20px; + font-size: 10px; + color: #000; + opacity: 1; + background: rgba(0, 0, 0, 0.2); +} + +.swiper-pagination-bullet-active { + color: #fff; + background: #007aff; } .default-container { @@ -916,12 +1049,14 @@ pre { } .vex.vex-theme-default .vex-content { - width: 95%; padding: 3px; + width: 95%; + padding: 3px; } .alarmImg { - vertical-align: top; - width:60px; height:60px; + vertical-align: top; + width: 60px; + height: 60px; } .alarmWarnCap { @@ -940,7 +1075,7 @@ pre { } .sectionBg { - box-shadow: 0 1px 1px rgba(0,0,0,0.16), 0 1px 1px rgba(0,0,0,0.23); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.16), 0 1px 1px rgba(0, 0, 0, 0.23); background: white; } @@ -952,7 +1087,7 @@ pre { } .sectionBgTile { - box-shadow: 0 1px 1px rgba(0,0,0,0.16), 0 1px 1px rgba(0,0,0,0.23); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.16), 0 1px 1px rgba(0, 0, 0, 0.23); background: white; } @@ -964,12 +1099,12 @@ pre { } .sectionBg table { - box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); background: white; } .sectionBgTile table { - box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); background: white; } @@ -981,6 +1116,7 @@ pre { text-decoration: underline; text-align: center; } + .devInfoTile th { color: #00a1db; background: transparent; @@ -989,6 +1125,7 @@ pre { text-decoration: underline; text-align: center; } + .redText { color: red; } @@ -1007,21 +1144,37 @@ pre { background: transparent; } -.chgLog ul, li { +.chgLog ul, +li { font-size: 12px; padding: 0 10px 0 10px; Margin: 0; } + .chgLog p { font-size: 12px; } +.hamburger-box { + width: 27px; + height: 24px; +} + +.hamburger-inner, +.hamburger-inner:after, +.hamburger-inner:before { + width: 27px; + height: 4px; +} + @media only screen and (max-width: 600px) { h1 { padding: 20px 0 !important; } - .hamburger-inner, .hamburger-inner:after, .hamburger-inner:before { - width: 25px; + .hamburger-inner, + .hamburger-inner:after, + .hamburger-inner:before { + width: 27px; height: 4px; } #rfrshBtn:after { @@ -1078,6 +1231,4 @@ pre { margin-left: 0; } -@media only screen and (min-width: 601px) { - -} +@media only screen and (min-width: 601px) {} \ No newline at end of file diff --git a/Documents/css/diagpages_new.min.css b/Documents/css/diagpages_new.min.css index 681237c87..c9b39ff0b 100644 --- a/Documents/css/diagpages_new.min.css +++ b/Documents/css/diagpages_new.min.css @@ -1 +1 @@ -html,body{position:relative;height:100%;min-height:100%;min-width:375px}.container{width:100%;margin:auto}#top-hdr{height:auto;min-width:375px}.in-middle{vertical-align:middle}.left-head-col{padding:1.2em 0 0 20px}.right-head-col{padding:2.2em 40px 0 0}.links{padding:10px;font-size:18px}.logoIcn{width:1.7em;height:auto;max-width:48px;max-height:48px}.refresh-btn{color:black;width:auto;height:auto;max-width:90px;max-height:40px;font-size:1.0em;border-radius:.4em;background-color:white;border-color:gray;border-style:solid;border-width:1px}#rfrshBtn:after{content:' Refresh'}.export-pdf-btn{color:white;width:auto;height:auto;max-width:90px;max-height:40px;font-size:1.0em;border-radius:.4em;background-color:transparent;border-color:white;border-style:solid;border-width:1px;display:none}.panel-title-text{font-size:1.2em}.subpanel-title-text{font-size:1em}.panel-heading{padding:0 10px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panelHeadTxt{font-size:25px}.pnl-head-title{font-size:2.0em}@media(min-width:800px){.pnl-head-title{padding:3px 0}}@media(min-width:600px){.pnl-head-title{padding:5px 0}}.title-text{font-size:2.0em}pre{overflow-x:auto;overflow-y:auto}.navMenu{text-align:left}.nav-home-btn{padding:20px 10px 0 10px;font-size:22px;-webkit-text-stroke:white;-webkit-text-stroke-width:thin}.nav-menu{padding:12px}.nav-menu li{border-bottom:solid 1px rgba(102,102,102,0.3);margin-left:5px;margin-right:5px;font-size:14px;padding:12px}.nav-menu li a{color:white;text-decoration:none}.nav-menu li a:hover{color:tomato;text-decoration:none}.nav-menu li .sub-nav{border-bottom:0;padding:4px}.nav-menu a .caret{width:0;height:0;display:inline-block;vertical-align:top;border-top:4px solid #4f5963;border-right:4px solid transparent;border-left:4px solid transparent;content:"";margin-top:8px}.nav-menu a:hover .caret{border-top-color:#4f5963}.nav-menu li.open>a>.caret{border-top:0;border-bottom:4px solid #4f5963;border-right:4px solid transparent;border-left:4px solid transparent}.nav-menu li.open>a:hover>.caret{border-bottom-color:#4f5963}.icon:before{font-family:'FontAwesome';font-style:normal;font-variant:normal;font-weight:normal;line-height:1;text-transform:none;content:'\f105'}.nav-menu li>a>span.icon{float:right;margin:.1em 1.7em -0.1em 0;opacity:0;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.nav-menu li>a:hover>span.icon{float:right;margin:.1em .8em -0.1em 0;opacity:1}.menu-btn:focus{outline:0}.nav-cont-bord-div{padding:15px 15px 25px 15px}.nav-cont-div{padding:10px;border-radius:.6em;background-color:#333;border:solid lightgray 1px;-moz-box-shadow:0 5px 1px #ccc;-webkit-box-shadow:0 1px 1px #ccc;box-shadow:0 1px 1px #ccc}.nav-key-item{font-weight:bold;text-decoration:underline;list-style:none;font-size:1.0em}.nav-subkey-item{font-weight:normal;list-style:none}.nav-subkey-item:before{color:white;content:"▶";padding-right:8px}.pushy{position:fixed;width:250px;height:100%;top:0;z-index:9999;background:#191918;opacity:.6;overflow:auto;-webkit-overflow-scrolling:touch}.pushy.pushy-left{left:0}.pushy.pushy-right{right:0}.pushy-left{-webkit-transform:translate3d(-250px,0,0);-ms-transform:translate3d(-250px,0,0);transform:translate3d(-250px,0,0)}.pushy-open-left #container,.pushy-open-left .push{-webkit-transform:translate3d(250px,0,0);-ms-transform:translate3d(250px,0,0);transform:translate3d(250px,0,0)}.pushy-right{-webkit-transform:translate3d(250px,0,0);-ms-transform:translate3d(250px,0,0);transform:translate3d(250px,0,0)}.pushy-open-right #container,.pushy-open-right .push{-webkit-transform:translate3d(-250px,0,0);-ms-transform:translate3d(-250px,0,0);transform:translate3d(-250px,0,0)}.pushy-open-left .pushy,.pushy-open-right .pushy{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.pushy-open-left .pushy-content,.pushy-open-right .pushy-content{visibility:visible}#container,.pushy,.push{transition:transform .2s cubic-bezier(0.16,0.68,0.43,0.99)}.pushy-content{transition:visibility .2s cubic-bezier(0.16,0.68,0.43,0.99)}.site-overlay{display:none}.pushy-open-left .site-overlay,.pushy-open-right .site-overlay{display:block;position:fixed;top:0;right:0;bottom:0;left:0;z-index:9998;background-color:rgba(0,0,0,0.5);-webkit-animation:fade 500ms;animation:fade 500ms}@keyframes fade{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fade{0%{opacity:0}100%{opacity:1}}.logs-div{text-align:left;vertical-align:middle;padding:0,0}.log-line{display:inline-block;padding-bottom:8px;vertical-align:middle}.log-time{font-weight:bold;vertical-align:middle}.log-type{display:inline-block;padding:.2em .6em .3em;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;border-radius:.25em;min-width:44px;font-size:.75em}.log-source{border-radius:.3em;border-color:gray;border-style:solid;border-width:1px;padding:2px;font-style:italic;vertical-align:middle}.log-msg{vertical-align:middle}.defsrc-bg{color:gray;background-color:white;font-size:.9em}.mansrc-bg{color:#6b6b6b;background-color:transparent;font-size:.9em}.autosrc-bg{color:#6b6b6b;background-color:lightgray;font-size:.9em}.camsrc-bg{color:#6b6b6b;background-color:lightblue;font-size:.9em}.protsrc-bg{color:#6b6b6b;background-color:lightorange;font-size:.9em}.pressrc-bg{color:#6b6b6b;background-color:lightyellow;font-size:.9em}.weatsrc-bg{color:#6b6b6b;background-color:lightpurple;font-size:.9em}.tstatsrc-bg{color:#6b6b6b;background-color:lightgreen;font-size:.9em}#scrollTopBtn{display:none;position:fixed;bottom:20px;right:30px;z-index:99;border:0;outline:0;background-color:gray;color:white;cursor:pointer;padding:15px;border-radius:10px}#scrollTopBtn:hover{background-color:#3174ae}.vex.vex-theme-default .vex-content{width:50%;padding:3px}.device table{border:0;border-radius:3px;width:100%;-webkit-border-radius:3px;-moz-border-radius:3px}.device h1,h2,h3,h4,h5,h6{padding:20px;margin:4px}.topBorder{border-top:2px solid #00a1db}.bottomBorder{border-bottom:2px solid #808080}.device{max-width:1200px;width:100%;padding-top:10px}.device h1{font-size:6vw;width:100%;text-align:center;font-weight:normal}.device h2{font-size:9vw;text-align:center;margin-left:auto;margin-right:auto;font-weight:normal}.device h3,h3 a{font-size:6vw;font-weight:bold;text-align:center;background:#b74c4c;color:#f5f5f5}.device h4{font-size:4vw;font-weight:bold;text-align:center;background:#00a1db;color:#f5f5f5}.centerText{text-align:center}.device hr{background:#00a1db;width:100%;height:1px}.device th,td{box-shadow:inset 0 0 rgba(0,0,0,0.25),inset 0 0 rgba(0,0,0,0.25);padding:4px}.device th{-webkit-font-smoothing:antialiased;color:#f5f5f5;text-shadow:0 0 1px rgba(0,0,0,0.1);-webkit-border-radius:2px;-moz-border-radius:2px;background:#00a1db}.devInfo th{font-size:3.8vw}.devInfoTile th{font-size:2.0vw}.devInfoTile h4{font-size:1.5vw}.device td{color:grey;text-shadow:0 0 1px rgba(255,255,255,0.1);text-align:center}.device tr{-webkit-transition:background .3s,box-shadow .3s;-moz-transition:background .3s,box-shadow .3s;transition:background .3s,box-shadow .3s}.column,.columns{width:100%;float:left;box-sizing:border-box}.one.column,.one.columns{width:4.66666666667%}.two.columns{width:13.3333333333%}.three.columns{width:22%}.four.columns{width:32.6666666667%}.five.columns{width:39.3333333333%}.six.columns{width:48%}.seven.columns{width:56.6666666667%}.eight.columns{width:65.3333333333%}.nine.columns{width:74.0%}.ten.columns{width:82.6666666667%}.eleven.columns{width:91.3333333333%}.twelve.columns{width:100%;margin-left:0}.offset-by-one.column,.offset-by-one.columns{margin-left:8.66666666667%}.offset-by-two.column,.offset-by-two.columns{margin-left:17.3333333333%}.offset-by-three.column,.offset-by-three.columns{margin-left:26%}.offset-by-four.column,.offset-by-four.columns{margin-left:34.6666666667%}.offset-by-five.column,.offset-by-five.columns{margin-left:43.3333333333%}.offset-by-six.column,.offset-by-six.columns{margin-left:52%}.offset-by-seven.column,.offset-by-seven.columns{margin-left:60.6666666667%}.offset-by-eight.column,.offset-by-eight.columns{margin-left:69.3333333333%}.offset-by-nine.column,.offset-by-nine.columns{margin-left:78.0%}.offset-by-ten.column,.offset-by-ten.columns{margin-left:86.6666666667%}.offset-by-eleven.column,.offset-by-eleven.columns{margin-left:95.3333333333%}.dateTimeText{font-size:3.4vw}.dateTimeTextTile{font-size:1.5vw}.dateTimeTextSmall{font-size:2.8vw}.battImg{width:30px;height:15px}.leafImg{width:25px;height:25px}.red{background-color:#db3a00}.yellow{background-color:#dba800}.redAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#b74c4c;color:#f5f5f5;padding:8px 0}.brightRedAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#ff3b19;color:#f5f5f5;padding:8px 0}.greenAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#0f0;-webkit-text-stroke:1.0px #000;-webkit-text-fill-color:#fff;padding:8px 0}.androidAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#6f786f;-webkit-text-stroke:1.0px #000;-webkit-text-fill-color:#fff;padding:8px 0}.orangeAlertBanner{font-size:6vw;font-weight:bold;text-align:center;background:#ffae19;color:#f5f5f5;padding:8px 0}.blueTitle{font-size:4vw;font-weight:bold;text-align:center;background:#00a1db;color:#f5f5f5}.alertModalTitle{font-size:22px;font-weight:bold;text-align:center;background:transparent;color:black}.sched h3{font-size:4.6vw;background:#00a1db}.sched h4{font-size:3.8vw;background:#00a1db}.sched col{font-size:4.0vw}.slideFooterMsg{font-size:3.0vw;padding:20px;margin:1em auto}.slideFooterMsgTile{font-size:1.8vw;padding:20px;margin:1em auto;text-decoration:underline}.pageFooterBtn{padding:10px;horizontal-align:center;text-align:center}.schedFill{background:gray;color:white;text-align:center;padding:4px}.tempSrc th{font-size:4.1vw;font-weight:bold;background:transparent;text-decoration:underline;color:gray}.swiper-container{width:95%;min-height:300px;padding:10px}.default-container{width:95%;padding:10px}.vex.vex-theme-default .vex-content{width:95%;padding:3px}.alarmImg{vertical-align:top;width:60px;height:60px}.alarmWarnCap{display:block;color:#e89a15}.alarmEmerCap{display:block;color:#df5316}.alarmClearCap{display:block;color:gray}.sectionBg{box-shadow:0 1px 1px rgba(0,0,0,0.16),0 1px 1px rgba(0,0,0,0.23);background:white}.sectionBg h3{background-color:#00a1db;font-size:4.5vw;padding:.6vw;text-shadow:1px 1px 1px black}.sectionBgTile{box-shadow:0 1px 1px rgba(0,0,0,0.16),0 1px 1px rgba(0,0,0,0.23);background:white}.sectionBgTile h3{background-color:#00a1db;font-size:2.5vw;padding:.6vw;text-shadow:1px 1px 1px black}.sectionBg table{box-shadow:0 3px 6px rgba(0,0,0,0.16),0 3px 6px rgba(0,0,0,0.23);background:white}.sectionBgTile table{box-shadow:0 3px 6px rgba(0,0,0,0.16),0 3px 6px rgba(0,0,0,0.23);background:white}.devInfo th{color:#00a1db;background:transparent;font-size:3.8vw;text-shadow:0 0 1px lightgray;text-decoration:underline;text-align:center}.devInfoTile th{color:#00a1db;background:transparent;font-size:2.0vw;text-shadow:0 0 1px lightgray;text-decoration:underline;text-align:center}.redText{color:red}.orangeText{color:orange}.chgLog div{padding:0 5px 0 5px;text-align:left}.chgLog h3{background-color:transparent;background:transparent}.chgLog ul,li{font-size:12px;padding:0 10px 0 10px;Margin:0}.chgLog p{font-size:12px}@media only screen and (max-width:600px){h1{padding:20px 0!important}.hamburger-inner,.hamburger-inner:after,.hamburger-inner:before{width:25px;height:4px}#rfrshBtn:after{content:''}#rfrshBtn{font-size:1.1em}.logoIcn{max-width:32px!important;max-height:32px!important}.title-text{font-size:6vw!important;padding:3.5vw 0!important}.container{padding-right:0!important;padding-left:0!important}.panel-body{padding:0 15px!important}.sectionBgTile h3{font-size:3.5vw!important}.device td{font-size:3.0vw!important}.devInfoTile th{font-size:3.0vw!important}.left-head-col{padding:3.2vw 0 0 0!important}.right-head-col{padding:1.7em 20px 0 0!important}.slideFooterMsg{font-size:2.8vw!important;text-decoration:underline}.slideFooterMsgTile{font-size:2.8vw!important;text-decoration:underline}b.wStation{font-size:2.5vw}}.row{margin-right:0;margin-left:0} \ No newline at end of file +.logs-div,.navMenu{text-align:left}body,html{position:relative;height:100%;min-height:100%;min-width:375px}.container{width:100%;margin:auto}#top-hdr{height:auto;min-width:375px}.in-middle{vertical-align:middle}.left-head-col{padding:1.2em 0 0 20px}.right-head-col{padding:2.2em 40px 0 0}.links{padding:10px;font-size:18px}.logoIcn{width:1.7em;height:auto;max-width:48px;max-height:48px}.export-pdf-btn,.refresh-btn{width:auto;height:auto;max-width:90px;max-height:40px;font-size:1em;border-radius:.4em;border-style:solid;border-width:1px}.refresh-btn{color:#000;background-color:#fff;border-color:gray}#rfrshBtn:after{content:' Refresh'}.export-pdf-btn{color:#fff;background-color:transparent;border-color:#fff;display:none}.nav-menu a .caret,.nav-menu li.open>a>.caret{border-right:4px solid transparent;border-left:4px solid transparent}.panel-title-text{font-size:1.2em}.subpanel-title-text{font-size:1em}.panel-heading{padding:0 10px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panelHeadTxt{font-size:25px}.pnl-head-title,.title-text{font-size:2em}@media (min-width:800px){.pnl-head-title{padding:3px 0}}@media (min-width:600px){.pnl-head-title{padding:5px 0}}pre{overflow-x:auto;overflow-y:auto}.nav-home-btn{padding:20px 10px 0;font-size:22px;-webkit-text-stroke:#fff;-webkit-text-stroke-width:thin}.nav-menu,.nav-menu li{padding:12px}.androidAlertBanner,.greenAlertBanner{-webkit-text-stroke:1px #000;-webkit-text-fill-color:#FFF}.nav-menu li{border-bottom:solid 1px rgba(102,102,102,.3);margin-left:5px;margin-right:5px;font-size:14px}.nav-menu li a{color:#fff;text-decoration:none}.nav-menu li a:hover{color:tomato;text-decoration:none}.nav-menu li .sub-nav{border-bottom:0;padding:4px}.nav-menu a .caret{width:0;height:0;display:inline-block;vertical-align:top;border-top:4px solid #4f5963;content:"";margin-top:8px}.nav-menu a:hover .caret{border-top-color:#4f5963}.nav-menu li.open>a>.caret{border-top:none;border-bottom:4px solid #4f5963}.nav-menu li.open>a:hover>.caret{border-bottom-color:#4f5963}.icon:before{font-family:FontAwesome;font-style:normal;font-variant:normal;font-weight:400;line-height:1;text-transform:none;content:'\f105'}.nav-menu li>a>span.icon{float:right;margin:.1em 1.7em -.1em 0;opacity:0;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.nav-menu li>a:hover>span.icon{float:right;margin:.1em .8em -.1em 0;opacity:1}.menu-btn:focus{outline:0}.nav-cont-bord-div{padding:15px 15px 25px}.nav-cont-div{padding:10px;border-radius:.6em;background-color:#333;border:1px solid #d3d3d3;-moz-box-shadow:0 5px 1px #ccc;-webkit-box-shadow:0 1px 1px #ccc;box-shadow:0 1px 1px #ccc}.nav-key-item{font-weight:700;text-decoration:underline;list-style:none;font-size:1em}.nav-subkey-item{font-weight:400;list-style:none}.nav-subkey-item:before{color:#fff;content:"â–¶";padding-right:8px}.pushy{position:fixed;width:250px;height:100%;top:0;z-index:9999;background:#191918;opacity:.6;overflow:auto;-webkit-overflow-scrolling:touch}.pushy.pushy-left{left:0}.pushy.pushy-right{right:0}.pushy-left{-webkit-transform:translate3d(-250px,0,0);-ms-transform:translate3d(-250px,0,0);transform:translate3d(-250px,0,0)}.pushy-open-left #container,.pushy-open-left .push,.pushy-right{-webkit-transform:translate3d(250px,0,0);-ms-transform:translate3d(250px,0,0);transform:translate3d(250px,0,0)}.pushy-open-right #container,.pushy-open-right .push{-webkit-transform:translate3d(-250px,0,0);-ms-transform:translate3d(-250px,0,0);transform:translate3d(-250px,0,0)}.pushy-open-left .pushy,.pushy-open-right .pushy{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.pushy-open-left .pushy-content,.pushy-open-right .pushy-content{visibility:visible}#container,.push,.pushy{transition:transform .2s cubic-bezier(.16,.68,.43,.99)}.pushy-content{transition:visibility .2s cubic-bezier(.16,.68,.43,.99)}.site-overlay{display:none}.pushy-open-left .site-overlay,.pushy-open-right .site-overlay{display:block;position:fixed;top:0;right:0;bottom:0;left:0;z-index:9998;background-color:rgba(0,0,0,.5);-webkit-animation:fade .5s;animation:fade .5s}.log-line,.log-type{display:inline-block;vertical-align:middle}@keyframes fade{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes fade{0%{opacity:0}100%{opacity:1}}.logs-div{vertical-align:middle;padding:0,}.log-line{padding-bottom:8px}.log-time{font-weight:700;vertical-align:middle}.log-type{padding:.2em .6em .3em;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;border-radius:.25em;min-width:44px;font-size:.75em}.device h1,.device h2{text-align:center;font-weight:400}.log-source{border-radius:.3em;border-color:gray;border-style:solid;border-width:1px;padding:2px;font-style:italic;vertical-align:middle}.log-msg{vertical-align:middle}.defsrc-bg{color:gray;background-color:#fff;font-size:.9em}.autosrc-bg,.camsrc-bg,.mansrc-bg,.pressrc-bg,.protsrc-bg,.tstatsrc-bg,.weatsrc-bg{color:#6b6b6b;font-size:.9em}.mansrc-bg{background-color:transparent}.autosrc-bg{background-color:#d3d3d3}.camsrc-bg{background-color:#add8e6}.protsrc-bg{background-color:lightorange}.pressrc-bg{background-color:#ffffe0}.weatsrc-bg{background-color:lightpurple}.tstatsrc-bg{background-color:#90ee90}#scrollTopBtn{display:none;position:fixed;bottom:20px;right:30px;z-index:99;border:none;outline:0;background-color:gray;color:#fff;cursor:pointer;padding:15px;border-radius:10px}#scrollTopBtn:hover{background-color:#3174AE}.device table{border:none;border-radius:3px;width:100%;-webkit-border-radius:3px;-moz-border-radius:3px}.device h1,h2,h3,h4,h5,h6{padding:20px;margin:4px}.topBorder{border-top:2px solid #00a1db}.bottomBorder{border-bottom:2px solid grey}.device{max-width:1200px;width:100%;padding-top:10px}.device h1{font-size:6vw;width:100%}.device h2{font-size:9vw;margin-left:auto;margin-right:auto}.device h3,.device h4,h3 a{font-weight:700;color:#f5f5f5;text-align:center}.device h3,h3 a{font-size:6vw;background:#B74C4C}.device h4,.device hr,.device th{background:#00a1db}.device h4{font-size:4vw}.centerText{text-align:center}.device hr{width:100%;height:1px}.device th,td{box-shadow:inset 0 0 rgba(0,0,0,.25),inset 0 0 rgba(0,0,0,.25);padding:4px}.sectionBg,.sectionBgTile{box-shadow:0 1px 1px rgba(0,0,0,.16),0 1px 1px rgba(0,0,0,.23)}.device th{-webkit-font-smoothing:antialiased;color:#f5f5f5;text-shadow:0 0 1px rgba(0,0,0,.1);-webkit-border-radius:2px;-moz-border-radius:2px}.devInfoTile h4{font-size:1.5vw}.device td{color:grey;text-shadow:0 0 1px rgba(255,255,255,.1);text-align:center}.device tr{-webkit-transition:background .3s,box-shadow .3s;-moz-transition:background .3s,box-shadow .3s;transition:background .3s,box-shadow .3s}.column,.columns{width:100%;float:left;box-sizing:border-box}.one.column,.one.columns{width:4.66666666667%}.two.columns{width:13.3333333333%}.three.columns{width:22%}.four.columns{width:32.6666666667%}.five.columns{width:39.3333333333%}.six.columns{width:48%}.seven.columns{width:56.6666666667%}.eight.columns{width:65.3333333333%}.nine.columns{width:74%}.ten.columns{width:82.6666666667%}.eleven.columns{width:91.3333333333%}.twelve.columns{width:100%;margin-left:0}.offset-by-one.column,.offset-by-one.columns{margin-left:8.66666666667%}.offset-by-two.column,.offset-by-two.columns{margin-left:17.3333333333%}.offset-by-three.column,.offset-by-three.columns{margin-left:26%}.offset-by-four.column,.offset-by-four.columns{margin-left:34.6666666667%}.offset-by-five.column,.offset-by-five.columns{margin-left:43.3333333333%}.offset-by-six.column,.offset-by-six.columns{margin-left:52%}.offset-by-seven.column,.offset-by-seven.columns{margin-left:60.6666666667%}.offset-by-eight.column,.offset-by-eight.columns{margin-left:69.3333333333%}.offset-by-nine.column,.offset-by-nine.columns{margin-left:78%}.offset-by-ten.column,.offset-by-ten.columns{margin-left:86.6666666667%}.offset-by-eleven.column,.offset-by-eleven.columns{margin-left:95.3333333333%}.dateTimeText{font-size:3.4vw}.dateTimeTextTile{font-size:1.5vw}.dateTimeTextSmall{font-size:2.8vw}.androidAlertBanner,.brightRedAlertBanner,.greenAlertBanner,.orangeAlertBanner,.redAlertBanner{font-size:6vw;padding:8px 0;font-weight:700;text-align:center}.battImg{width:30px;height:15px}.leafImg{width:25px;height:25px}.red{background-color:#db3a00}.yellow{background-color:#dba800}.redAlertBanner{background:#B74C4C;color:#f5f5f5}.brightRedAlertBanner{background:#ff3b19;color:#f5f5f5}.greenAlertBanner{background:#0f0}.androidAlertBanner{background:#6f786f}.orangeAlertBanner{background:#ffae19;color:#f5f5f5}.blueTitle{font-size:4vw;font-weight:700;text-align:center;background:#00a1db;color:#f5f5f5}.alertModalTitle{font-size:22px;font-weight:700;text-align:center;background:0 0;color:#000}.sched h3{font-size:4.6vw;background:#00a1db}.sched h4{font-size:3.8vw;background:#00a1db}.sched col{font-size:4vw}.slideFooterMsg,.slideFooterTextTile{font-size:1.8vw;margin:1em auto;text-decoration:underline}.slideFooterMsg{padding:20px}.pageFooterBtn{padding:10px;text-align:center}.schedFill{background:gray;color:#fff;text-align:center;padding:4px}.tempSrc th{font-size:4.1vw;font-weight:700;background:0 0;text-decoration:underline;color:gray}.slideFooterBtn{font-size:1rem;text-align:center;padding:0}.slideFooterText{font-size:3vw;margin:1em auto;padding:0;text-decoration:underline}.pageFooterCls{text-align:center}.swiper-container{width:95%;min-height:300px;padding:0 10px!important}.swiper-pagination-bullet{width:20px;height:20px;text-align:center;line-height:20px;font-size:10px;color:#000;opacity:1;background:rgba(0,0,0,.2)}.swiper-pagination-bullet-active{color:#fff;background:#007aff}.default-container{width:95%;padding:10px}.vex.vex-theme-default .vex-content{width:95%;padding:3px}.sectionBg h3,.sectionBgTile h3{padding:.6vw;text-shadow:1px 1px 1px #000}.alarmImg{vertical-align:top;width:60px;height:60px}.alarmWarnCap{display:block;color:#e89a15}.alarmEmerCap{display:block;color:#df5316}.alarmClearCap{display:block;color:gray}.sectionBg{background:#fff}.sectionBg h3{background-color:#00a1db;font-size:4.5vw}.sectionBgTile{background:#fff}.sectionBgTile h3{background-color:#00a1db;font-size:2.5vw}.devInfo th,.devInfoTile th{color:#00a1db;text-shadow:0 0 1px #d3d3d3;text-decoration:underline;text-align:center}.sectionBg table,.sectionBgTile table{box-shadow:0 3px 6px rgba(0,0,0,.16),0 3px 6px rgba(0,0,0,.23);background:#fff}.chgLog h3,.devInfo th{background:0 0}.devInfo th{font-size:3.8vw}.devInfoTile th{background:0 0;font-size:2vw}.chgLog p,.chgLog ul,li{font-size:12px}.redText{color:red}.orangeText{color:orange}.chgLog div{padding:0 5px;text-align:left}.chgLog ul,li{padding:0 10px;Margin:0}.hamburger-box{width:27px;height:24px}.hamburger-inner,.hamburger-inner:after,.hamburger-inner:before{width:27px;height:4px}@media only screen and (max-width:600px){h1{padding:20px 0!important}.hamburger-inner,.hamburger-inner:after,.hamburger-inner:before{width:27px;height:4px}#rfrshBtn:after{content:''}#rfrshBtn{font-size:1.1em}.logoIcn{max-width:32px!important;max-height:32px!important}.title-text{font-size:6vw!important;padding:3.5vw 0!important}.container{padding-right:0!important;padding-left:0!important}.panel-body{padding:0 15px!important}.sectionBgTile h3{font-size:3.5vw!important}.devInfoTile th,.device td{font-size:3vw!important}.left-head-col{padding:3.2vw 0 0!important}.right-head-col{padding:1.7em 20px 0 0!important}.slideFooterMsg,.slideFooterMsgTile{font-size:2.8vw!important;text-decoration:underline}b.wStation{font-size:2.5vw}}.row{margin-right:0;margin-left:0} \ No newline at end of file diff --git a/Documents/css/nst_master.css b/Documents/css/nst_master.css new file mode 100644 index 000000000..d6ebf038c --- /dev/null +++ b/Documents/css/nst_master.css @@ -0,0 +1,30006 @@ +.pswp__container, +.pswp__img, +.waves-effect, +a, +html { + -webkit-tap-highlight-color: transparent +} + +[tabindex="-1"]:focus, +button:focus { + outline: 0!important +} + +address, +dl, +ol, +p, +ul { + margin-bottom: 1rem +} + +body, +caption { + text-align: left +} + +dd, +h1, +h2, +h3, +h4, +h5, +h6, +label { + margin-bottom: .5rem +} + +button, +hr, +input { + overflow: visible +} + +address, +legend { + line-height: inherit +} + +progress, +sub, +sup { + vertical-align: baseline +} + +pre, +textarea { + overflow: auto +} + +.btn, +.custom-control-indicator { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none +} + +.btn-outline-danger, +.btn-outline-dark, +.btn-outline-info, +.btn-outline-light, +.btn-outline-primary, +.btn-outline-secondary, +.btn-outline-success, +.btn-outline-warning, +.btn:not([disabled]):not(.disabled).active, +.btn:not([disabled]):not(.disabled):active { + background-image: none +} + +.pswp, +html { + -webkit-text-size-adjust: 100% +} + +.dropdown-menu, +.nav, +.navbar-nav { + list-style: none +} + +:root { + --blue: #007bff; + --indigo: #6610f2; + --purple: #6f42c1; + --pink: #e83e8c; + --red: #dc3545; + --orange: #fd7e14; + --yellow: #ffc107; + --green: #28a745; + --teal: #20c997; + --cyan: #17a2b8; + --white: #fff; + --gray: #868e96; + --gray-dark: #343a40; + --primary: #007bff; + --secondary: #868e96; + --success: #28a745; + --info: #17a2b8; + --warning: #ffc107; + --danger: #dc3545; + --light: #f8f9fa; + --dark: #343a40; + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + --font-family-monospace: "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace +} + +@media print { + blockquote, + img, + pre, + tr { + page-break-inside: avoid + } + *, + ::after, + ::before { + text-shadow: none!important; + -webkit-box-shadow: none!important; + box-shadow: none!important + } + a, + a:visited { + text-decoration: underline + } + abbr[title]::after { + content: " (" attr(title) ")" + } + pre { + white-space: pre-wrap!important + } + blockquote, + pre { + border: 1px solid #999 + } + thead { + display: table-header-group + } + h2, + h3, + p { + orphans: 3; + widows: 3 + } + h2, + h3 { + page-break-after: avoid + } + .navbar { + display: none + } + .badge { + border: 1px solid #000 + } + .table { + border-collapse: collapse!important + } + .table td, + .table th { + background-color: #fff!important + } + .table-bordered td, + .table-bordered th { + border: 1px solid #ddd!important + } +} + +article, +aside, +dialog, +figcaption, +figure, +footer, +header, +hgroup, +legend, +main, +nav, +section { + display: block +} + +label, +output { + display: inline-block +} + +*, +::after, +::before { + -webkit-box-sizing: border-box; + box-sizing: border-box +} + +html { + font-family: sans-serif; + line-height: 1.15; + -ms-text-size-adjust: 100%; + -ms-overflow-style: scrollbar +} + +@-ms-viewport { + width: device-width +} + +body { + margin: 0; + font-size: 1rem; + line-height: 1.5; + color: #212529; + background-color: #fff +} + +hr { + -webkit-box-sizing: content-box; + box-sizing: content-box; + height: 0 +} + +dl, +h1, +h2, +h3, +h4, +h5, +h6, +ol, +p, +ul { + margin-top: 0 +} + +abbr[data-original-title], +abbr[title] { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0 +} + +address { + font-style: normal +} + +ol ol, +ol ul, +ul ol, +ul ul { + margin-bottom: 0 +} + +dt { + font-weight: 700 +} + +dd { + margin-left: 0 +} + +blockquote, +figure { + margin: 0 0 1rem +} + +dfn { + font-style: italic +} + +b, +strong { + font-weight: bolder +} + +small { + font-size: 80% +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0 +} + +sub { + bottom: -.25em +} + +sup { + top: -.5em +} + +a { + background-color: transparent; + -webkit-text-decoration-skip: objects +} + +a:hover { + color: #0056b3 +} + +a:not([href]):not([tabindex]):focus { + outline: 0 +} + +code, +kbd, +pre, +samp { + font-size: 1em +} + +img { + vertical-align: middle; + border-style: none +} + +svg:not(:root) { + overflow: hidden +} + +[role=button], +a, +area, +button, +input:not([type=range]), +label, +select, +summary, +textarea { + -ms-touch-action: manipulation; + touch-action: manipulation +} + +table { + border-collapse: collapse +} + +caption { + padding-top: .75rem; + padding-bottom: .75rem; + color: #868e96; + caption-side: bottom +} + +th { + text-align: inherit +} + +button { + border-radius: 0 +} + +button, +input, +optgroup, +select, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit +} + +button, +select { + text-transform: none +} + +[type=button]::-moz-focus-inner, +[type=reset]::-moz-focus-inner, +[type=submit]::-moz-focus-inner, +button::-moz-focus-inner { + padding: 0; + border-style: none +} + +input[type=radio], +input[type=checkbox] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding: 0 +} + +input[type=date], +input[type=time], +input[type=datetime-local], +input[type=month] { + -webkit-appearance: listbox +} + +textarea { + resize: vertical +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0 +} + +legend { + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: 1.5rem; + color: inherit; + white-space: normal +} + +[type=number]::-webkit-inner-spin-button, +[type=number]::-webkit-outer-spin-button { + height: auto +} + +[type=search] { + outline-offset: -2px; + -webkit-appearance: none +} + +[type=search]::-webkit-search-cancel-button, +[type=search]::-webkit-search-decoration { + -webkit-appearance: none +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button +} + +.display-1, +.display-2, +.display-3, +.display-4 { + line-height: 1.2 +} + +summary { + display: list-item +} + +template { + display: none +} + +[hidden] { + display: none!important +} + +.h1, +.h2, +.h3, +.h4, +.h5, +.h6, +h1, +h2, +h3, +h4, +h5, +h6 { + margin-bottom: .5rem; + font-family: inherit; + font-weight: 500; + line-height: 1.2; + color: inherit +} + +.blockquote, +hr { + margin-bottom: 1rem +} + +.display-1, +.display-2, +.display-3, +.display-4, +.lead { + font-weight: 300 +} + +.h1, +h1 { + font-size: 2.5rem +} + +.h2, +h2 { + font-size: 2rem +} + +.h3, +h3 { + font-size: 1.75rem +} + +.h4, +h4 { + font-size: 1.5rem +} + +.h5, +h5 { + font-size: 1.25rem +} + +.h6, +h6 { + font-size: 1rem +} + +.lead { + font-size: 1.25rem +} + +.display-1 { + font-size: 6rem +} + +.display-2 { + font-size: 5.5rem +} + +.display-3 { + font-size: 4.5rem +} + +.display-4 { + font-size: 3.5rem +} + +hr { + margin-top: 1rem; + border: 0; + border-top: 1px solid rgba(0, 0, 0, .1) +} + +.small, +small { + font-size: 80%; + font-weight: 400 +} + +.mark, +mark { + padding: .2em; + background-color: #fcf8e3 +} + +.list-inline, +.list-unstyled { + padding-left: 0; + list-style: none +} + +.list-inline-item { + display: inline-block +} + +.list-inline-item:not(:last-child) { + margin-right: 5px +} + +.initialism { + font-size: 90%; + text-transform: uppercase +} + +.blockquote { + font-size: 1.25rem +} + +.blockquote-footer { + display: block; + font-size: 80%; + color: #868e96 +} + +code, +kbd { + font-size: 90% +} + +.blockquote-footer::before { + content: "\2014 \00A0" +} + +.img-thumbnail { + padding: .25rem; + background-color: #fff; + border: 1px solid #ddd; + border-radius: .25rem; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; + max-width: 100%; + height: auto +} + +.figure { + display: inline-block +} + +.figure-img { + margin-bottom: .5rem; + line-height: 1 +} + +.table, +pre { + margin-bottom: 1rem +} + +.figure-caption { + font-size: 90%; + color: #868e96 +} + +a>code, +pre code { + padding: 0; + color: inherit +} + +code, +kbd, +pre, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace +} + +code { + padding: .2rem .4rem; + color: #bd4147; + background-color: #f8f9fa; + border-radius: .25rem +} + +a>code { + background-color: inherit +} + +kbd { + padding: .2rem .4rem; + color: #fff; + background-color: #212529; + border-radius: .2rem +} + +.table, +pre code { + background-color: transparent +} + +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: 700 +} + +.btn, +.btn-link, +.dropdown-item { + font-weight: 400 +} + +pre { + -ms-overflow-style: scrollbar; + display: block; + margin-top: 0; + font-size: 90%; + color: #212529 +} + +.form-check-input, +.form-text, +.valid-feedback { + margin-top: .25rem +} + +pre code { + font-size: inherit; + border-radius: 0 +} + +.container, +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; + width: 100% +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll +} + +@media (min-width: 576px) { + .container { + max-width: 540px + } +} + +@media (min-width: 768px) { + .container { + max-width: 720px + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px + } +} + +.row { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -15px; + margin-left: -15px +} + +.form-control, +.form-control-file, +.form-control-range, +.form-text { + display: block +} + +.no-gutters { + margin-right: 0; + margin-left: 0 +} + +.no-gutters>.col, +.no-gutters>[class*=col-] { + padding-right: 0; + padding-left: 0 +} + +.col, +.col-1, +.col-10, +.col-11, +.col-12, +.col-2, +.col-3, +.col-4, +.col-5, +.col-6, +.col-7, +.col-8, +.col-9, +.col-auto, +.col-lg, +.col-lg-1, +.col-lg-10, +.col-lg-11, +.col-lg-12, +.col-lg-2, +.col-lg-3, +.col-lg-4, +.col-lg-5, +.col-lg-6, +.col-lg-7, +.col-lg-8, +.col-lg-9, +.col-lg-auto, +.col-md, +.col-md-1, +.col-md-10, +.col-md-11, +.col-md-12, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-auto, +.col-sm, +.col-sm-1, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-sm-auto, +.col-xl, +.col-xl-1, +.col-xl-10, +.col-xl-11, +.col-xl-12, +.col-xl-2, +.col-xl-3, +.col-xl-4, +.col-xl-5, +.col-xl-6, +.col-xl-7, +.col-xl-8, +.col-xl-9, +.col-xl-auto { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px +} + +.col { + -ms-flex-preferred-size: 0; + -webkit-flex-basis: 0; + flex-basis: 0; + -ms-flex-positive: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + max-width: 100% +} + +.col-auto { + -ms-flex: 0 0 auto; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none +} + +.col-1 { + -ms-flex: 0 0 8.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% +} + +.col-2 { + -ms-flex: 0 0 16.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% +} + +.col-3 { + -ms-flex: 0 0 25%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% +} + +.col-4 { + -ms-flex: 0 0 33.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% +} + +.col-5 { + -ms-flex: 0 0 41.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% +} + +.col-6 { + -ms-flex: 0 0 50%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% +} + +.col-7 { + -ms-flex: 0 0 58.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% +} + +.col-8 { + -ms-flex: 0 0 66.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% +} + +.col-9 { + -ms-flex: 0 0 75%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% +} + +.col-10 { + -ms-flex: 0 0 83.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% +} + +.col-11 { + -ms-flex: 0 0 91.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% +} + +.col-12 { + -ms-flex: 0 0 100%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% +} + +.order-first { + -ms-flex-order: -1; + -webkit-box-ordinal-group: 0; + -webkit-order: -1; + order: -1 +} + +.order-1 { + -ms-flex-order: 1; + -webkit-box-ordinal-group: 2; + -webkit-order: 1; + order: 1 +} + +.order-2 { + -ms-flex-order: 2; + -webkit-box-ordinal-group: 3; + -webkit-order: 2; + order: 2 +} + +.order-3 { + -ms-flex-order: 3; + -webkit-box-ordinal-group: 4; + -webkit-order: 3; + order: 3 +} + +.order-4 { + -ms-flex-order: 4; + -webkit-box-ordinal-group: 5; + -webkit-order: 4; + order: 4 +} + +.order-5 { + -ms-flex-order: 5; + -webkit-box-ordinal-group: 6; + -webkit-order: 5; + order: 5 +} + +.order-6 { + -ms-flex-order: 6; + -webkit-box-ordinal-group: 7; + -webkit-order: 6; + order: 6 +} + +.order-7 { + -ms-flex-order: 7; + -webkit-box-ordinal-group: 8; + -webkit-order: 7; + order: 7 +} + +.order-8 { + -ms-flex-order: 8; + -webkit-box-ordinal-group: 9; + -webkit-order: 8; + order: 8 +} + +.order-9 { + -ms-flex-order: 9; + -webkit-box-ordinal-group: 10; + -webkit-order: 9; + order: 9 +} + +.order-10 { + -ms-flex-order: 10; + -webkit-box-ordinal-group: 11; + -webkit-order: 10; + order: 10 +} + +.order-11 { + -ms-flex-order: 11; + -webkit-box-ordinal-group: 12; + -webkit-order: 11; + order: 11 +} + +.order-12 { + -ms-flex-order: 12; + -webkit-box-ordinal-group: 13; + -webkit-order: 12; + order: 12 +} + +.offset-1 { + margin-left: 8.333333% +} + +.offset-2 { + margin-left: 16.666667% +} + +.offset-3 { + margin-left: 25% +} + +.offset-4 { + margin-left: 33.333333% +} + +.offset-5 { + margin-left: 41.666667% +} + +.offset-6 { + margin-left: 50% +} + +.offset-7 { + margin-left: 58.333333% +} + +.offset-8 { + margin-left: 66.666667% +} + +.offset-9 { + margin-left: 75% +} + +.offset-10 { + margin-left: 83.333333% +} + +.offset-11 { + margin-left: 91.666667% +} + +@media (min-width: 576px) { + .col-sm { + -ms-flex-preferred-size: 0; + -webkit-flex-basis: 0; + flex-basis: 0; + -ms-flex-positive: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + max-width: 100% + } + .col-sm-auto { + -ms-flex: 0 0 auto; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none + } + .col-sm-1 { + -ms-flex: 0 0 8.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% + } + .col-sm-2 { + -ms-flex: 0 0 16.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% + } + .col-sm-3 { + -ms-flex: 0 0 25%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% + } + .col-sm-4 { + -ms-flex: 0 0 33.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% + } + .col-sm-5 { + -ms-flex: 0 0 41.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% + } + .col-sm-6 { + -ms-flex: 0 0 50%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% + } + .col-sm-7 { + -ms-flex: 0 0 58.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% + } + .col-sm-8 { + -ms-flex: 0 0 66.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% + } + .col-sm-9 { + -ms-flex: 0 0 75%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% + } + .col-sm-10 { + -ms-flex: 0 0 83.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% + } + .col-sm-11 { + -ms-flex: 0 0 91.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% + } + .col-sm-12 { + -ms-flex: 0 0 100%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% + } + .order-sm-first { + -ms-flex-order: -1; + -webkit-box-ordinal-group: 0; + -webkit-order: -1; + order: -1 + } + .order-sm-1 { + -ms-flex-order: 1; + -webkit-box-ordinal-group: 2; + -webkit-order: 1; + order: 1 + } + .order-sm-2 { + -ms-flex-order: 2; + -webkit-box-ordinal-group: 3; + -webkit-order: 2; + order: 2 + } + .order-sm-3 { + -ms-flex-order: 3; + -webkit-box-ordinal-group: 4; + -webkit-order: 3; + order: 3 + } + .order-sm-4 { + -ms-flex-order: 4; + -webkit-box-ordinal-group: 5; + -webkit-order: 4; + order: 4 + } + .order-sm-5 { + -ms-flex-order: 5; + -webkit-box-ordinal-group: 6; + -webkit-order: 5; + order: 5 + } + .order-sm-6 { + -ms-flex-order: 6; + -webkit-box-ordinal-group: 7; + -webkit-order: 6; + order: 6 + } + .order-sm-7 { + -ms-flex-order: 7; + -webkit-box-ordinal-group: 8; + -webkit-order: 7; + order: 7 + } + .order-sm-8 { + -ms-flex-order: 8; + -webkit-box-ordinal-group: 9; + -webkit-order: 8; + order: 8 + } + .order-sm-9 { + -ms-flex-order: 9; + -webkit-box-ordinal-group: 10; + -webkit-order: 9; + order: 9 + } + .order-sm-10 { + -ms-flex-order: 10; + -webkit-box-ordinal-group: 11; + -webkit-order: 10; + order: 10 + } + .order-sm-11 { + -ms-flex-order: 11; + -webkit-box-ordinal-group: 12; + -webkit-order: 11; + order: 11 + } + .order-sm-12 { + -ms-flex-order: 12; + -webkit-box-ordinal-group: 13; + -webkit-order: 12; + order: 12 + } + .offset-sm-0 { + margin-left: 0 + } + .offset-sm-1 { + margin-left: 8.333333% + } + .offset-sm-2 { + margin-left: 16.666667% + } + .offset-sm-3 { + margin-left: 25% + } + .offset-sm-4 { + margin-left: 33.333333% + } + .offset-sm-5 { + margin-left: 41.666667% + } + .offset-sm-6 { + margin-left: 50% + } + .offset-sm-7 { + margin-left: 58.333333% + } + .offset-sm-8 { + margin-left: 66.666667% + } + .offset-sm-9 { + margin-left: 75% + } + .offset-sm-10 { + margin-left: 83.333333% + } + .offset-sm-11 { + margin-left: 91.666667% + } +} + +@media (min-width: 768px) { + .col-md { + -ms-flex-preferred-size: 0; + -webkit-flex-basis: 0; + flex-basis: 0; + -ms-flex-positive: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + max-width: 100% + } + .col-md-auto { + -ms-flex: 0 0 auto; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none + } + .col-md-1 { + -ms-flex: 0 0 8.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% + } + .col-md-2 { + -ms-flex: 0 0 16.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% + } + .col-md-3 { + -ms-flex: 0 0 25%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% + } + .col-md-4 { + -ms-flex: 0 0 33.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% + } + .col-md-5 { + -ms-flex: 0 0 41.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% + } + .col-md-6 { + -ms-flex: 0 0 50%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% + } + .col-md-7 { + -ms-flex: 0 0 58.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% + } + .col-md-8 { + -ms-flex: 0 0 66.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% + } + .col-md-9 { + -ms-flex: 0 0 75%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% + } + .col-md-10 { + -ms-flex: 0 0 83.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% + } + .col-md-11 { + -ms-flex: 0 0 91.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% + } + .col-md-12 { + -ms-flex: 0 0 100%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% + } + .order-md-first { + -ms-flex-order: -1; + -webkit-box-ordinal-group: 0; + -webkit-order: -1; + order: -1 + } + .order-md-1 { + -ms-flex-order: 1; + -webkit-box-ordinal-group: 2; + -webkit-order: 1; + order: 1 + } + .order-md-2 { + -ms-flex-order: 2; + -webkit-box-ordinal-group: 3; + -webkit-order: 2; + order: 2 + } + .order-md-3 { + -ms-flex-order: 3; + -webkit-box-ordinal-group: 4; + -webkit-order: 3; + order: 3 + } + .order-md-4 { + -ms-flex-order: 4; + -webkit-box-ordinal-group: 5; + -webkit-order: 4; + order: 4 + } + .order-md-5 { + -ms-flex-order: 5; + -webkit-box-ordinal-group: 6; + -webkit-order: 5; + order: 5 + } + .order-md-6 { + -ms-flex-order: 6; + -webkit-box-ordinal-group: 7; + -webkit-order: 6; + order: 6 + } + .order-md-7 { + -ms-flex-order: 7; + -webkit-box-ordinal-group: 8; + -webkit-order: 7; + order: 7 + } + .order-md-8 { + -ms-flex-order: 8; + -webkit-box-ordinal-group: 9; + -webkit-order: 8; + order: 8 + } + .order-md-9 { + -ms-flex-order: 9; + -webkit-box-ordinal-group: 10; + -webkit-order: 9; + order: 9 + } + .order-md-10 { + -ms-flex-order: 10; + -webkit-box-ordinal-group: 11; + -webkit-order: 10; + order: 10 + } + .order-md-11 { + -ms-flex-order: 11; + -webkit-box-ordinal-group: 12; + -webkit-order: 11; + order: 11 + } + .order-md-12 { + -ms-flex-order: 12; + -webkit-box-ordinal-group: 13; + -webkit-order: 12; + order: 12 + } + .offset-md-0 { + margin-left: 0 + } + .offset-md-1 { + margin-left: 8.333333% + } + .offset-md-2 { + margin-left: 16.666667% + } + .offset-md-3 { + margin-left: 25% + } + .offset-md-4 { + margin-left: 33.333333% + } + .offset-md-5 { + margin-left: 41.666667% + } + .offset-md-6 { + margin-left: 50% + } + .offset-md-7 { + margin-left: 58.333333% + } + .offset-md-8 { + margin-left: 66.666667% + } + .offset-md-9 { + margin-left: 75% + } + .offset-md-10 { + margin-left: 83.333333% + } + .offset-md-11 { + margin-left: 91.666667% + } +} + +@media (min-width: 992px) { + .col-lg { + -ms-flex-preferred-size: 0; + -webkit-flex-basis: 0; + flex-basis: 0; + -ms-flex-positive: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + max-width: 100% + } + .col-lg-auto { + -ms-flex: 0 0 auto; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none + } + .col-lg-1 { + -ms-flex: 0 0 8.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% + } + .col-lg-2 { + -ms-flex: 0 0 16.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% + } + .col-lg-3 { + -ms-flex: 0 0 25%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% + } + .col-lg-4 { + -ms-flex: 0 0 33.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% + } + .col-lg-5 { + -ms-flex: 0 0 41.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% + } + .col-lg-6 { + -ms-flex: 0 0 50%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% + } + .col-lg-7 { + -ms-flex: 0 0 58.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% + } + .col-lg-8 { + -ms-flex: 0 0 66.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% + } + .col-lg-9 { + -ms-flex: 0 0 75%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% + } + .col-lg-10 { + -ms-flex: 0 0 83.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% + } + .col-lg-11 { + -ms-flex: 0 0 91.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% + } + .col-lg-12 { + -ms-flex: 0 0 100%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% + } + .order-lg-first { + -ms-flex-order: -1; + -webkit-box-ordinal-group: 0; + -webkit-order: -1; + order: -1 + } + .order-lg-1 { + -ms-flex-order: 1; + -webkit-box-ordinal-group: 2; + -webkit-order: 1; + order: 1 + } + .order-lg-2 { + -ms-flex-order: 2; + -webkit-box-ordinal-group: 3; + -webkit-order: 2; + order: 2 + } + .order-lg-3 { + -ms-flex-order: 3; + -webkit-box-ordinal-group: 4; + -webkit-order: 3; + order: 3 + } + .order-lg-4 { + -ms-flex-order: 4; + -webkit-box-ordinal-group: 5; + -webkit-order: 4; + order: 4 + } + .order-lg-5 { + -ms-flex-order: 5; + -webkit-box-ordinal-group: 6; + -webkit-order: 5; + order: 5 + } + .order-lg-6 { + -ms-flex-order: 6; + -webkit-box-ordinal-group: 7; + -webkit-order: 6; + order: 6 + } + .order-lg-7 { + -ms-flex-order: 7; + -webkit-box-ordinal-group: 8; + -webkit-order: 7; + order: 7 + } + .order-lg-8 { + -ms-flex-order: 8; + -webkit-box-ordinal-group: 9; + -webkit-order: 8; + order: 8 + } + .order-lg-9 { + -ms-flex-order: 9; + -webkit-box-ordinal-group: 10; + -webkit-order: 9; + order: 9 + } + .order-lg-10 { + -ms-flex-order: 10; + -webkit-box-ordinal-group: 11; + -webkit-order: 10; + order: 10 + } + .order-lg-11 { + -ms-flex-order: 11; + -webkit-box-ordinal-group: 12; + -webkit-order: 11; + order: 11 + } + .order-lg-12 { + -ms-flex-order: 12; + -webkit-box-ordinal-group: 13; + -webkit-order: 12; + order: 12 + } + .offset-lg-0 { + margin-left: 0 + } + .offset-lg-1 { + margin-left: 8.333333% + } + .offset-lg-2 { + margin-left: 16.666667% + } + .offset-lg-3 { + margin-left: 25% + } + .offset-lg-4 { + margin-left: 33.333333% + } + .offset-lg-5 { + margin-left: 41.666667% + } + .offset-lg-6 { + margin-left: 50% + } + .offset-lg-7 { + margin-left: 58.333333% + } + .offset-lg-8 { + margin-left: 66.666667% + } + .offset-lg-9 { + margin-left: 75% + } + .offset-lg-10 { + margin-left: 83.333333% + } + .offset-lg-11 { + margin-left: 91.666667% + } +} + +@media (min-width: 1200px) { + .col-xl { + -ms-flex-preferred-size: 0; + -webkit-flex-basis: 0; + flex-basis: 0; + -ms-flex-positive: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + max-width: 100% + } + .col-xl-auto { + -ms-flex: 0 0 auto; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none + } + .col-xl-1 { + -ms-flex: 0 0 8.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333% + } + .col-xl-2 { + -ms-flex: 0 0 16.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667% + } + .col-xl-3 { + -ms-flex: 0 0 25%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25% + } + .col-xl-4 { + -ms-flex: 0 0 33.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333% + } + .col-xl-5 { + -ms-flex: 0 0 41.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667% + } + .col-xl-6 { + -ms-flex: 0 0 50%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50% + } + .col-xl-7 { + -ms-flex: 0 0 58.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333% + } + .col-xl-8 { + -ms-flex: 0 0 66.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667% + } + .col-xl-9 { + -ms-flex: 0 0 75%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75% + } + .col-xl-10 { + -ms-flex: 0 0 83.333333%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333% + } + .col-xl-11 { + -ms-flex: 0 0 91.666667%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667% + } + .col-xl-12 { + -ms-flex: 0 0 100%; + -webkit-box-flex: 0; + -webkit-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100% + } + .order-xl-first { + -ms-flex-order: -1; + -webkit-box-ordinal-group: 0; + -webkit-order: -1; + order: -1 + } + .order-xl-1 { + -ms-flex-order: 1; + -webkit-box-ordinal-group: 2; + -webkit-order: 1; + order: 1 + } + .order-xl-2 { + -ms-flex-order: 2; + -webkit-box-ordinal-group: 3; + -webkit-order: 2; + order: 2 + } + .order-xl-3 { + -ms-flex-order: 3; + -webkit-box-ordinal-group: 4; + -webkit-order: 3; + order: 3 + } + .order-xl-4 { + -ms-flex-order: 4; + -webkit-box-ordinal-group: 5; + -webkit-order: 4; + order: 4 + } + .order-xl-5 { + -ms-flex-order: 5; + -webkit-box-ordinal-group: 6; + -webkit-order: 5; + order: 5 + } + .order-xl-6 { + -ms-flex-order: 6; + -webkit-box-ordinal-group: 7; + -webkit-order: 6; + order: 6 + } + .order-xl-7 { + -ms-flex-order: 7; + -webkit-box-ordinal-group: 8; + -webkit-order: 7; + order: 7 + } + .order-xl-8 { + -ms-flex-order: 8; + -webkit-box-ordinal-group: 9; + -webkit-order: 8; + order: 8 + } + .order-xl-9 { + -ms-flex-order: 9; + -webkit-box-ordinal-group: 10; + -webkit-order: 9; + order: 9 + } + .order-xl-10 { + -ms-flex-order: 10; + -webkit-box-ordinal-group: 11; + -webkit-order: 10; + order: 10 + } + .order-xl-11 { + -ms-flex-order: 11; + -webkit-box-ordinal-group: 12; + -webkit-order: 11; + order: 11 + } + .order-xl-12 { + -ms-flex-order: 12; + -webkit-box-ordinal-group: 13; + -webkit-order: 12; + order: 12 + } + .offset-xl-0 { + margin-left: 0 + } + .offset-xl-1 { + margin-left: 8.333333% + } + .offset-xl-2 { + margin-left: 16.666667% + } + .offset-xl-3 { + margin-left: 25% + } + .offset-xl-4 { + margin-left: 33.333333% + } + .offset-xl-5 { + margin-left: 41.666667% + } + .offset-xl-6 { + margin-left: 50% + } + .offset-xl-7 { + margin-left: 58.333333% + } + .offset-xl-8 { + margin-left: 66.666667% + } + .offset-xl-9 { + margin-left: 75% + } + .offset-xl-10 { + margin-left: 83.333333% + } + .offset-xl-11 { + margin-left: 91.666667% + } +} + +.table { + width: 100%; + max-width: 100% +} + +.table td, +.table th { + padding: .75rem; + vertical-align: top; + border-top: 1px solid #e9ecef +} + +.table thead th { + vertical-align: bottom; + border-bottom: 2px solid #e9ecef +} + +.table tbody+tbody { + border-top: 2px solid #e9ecef +} + +.table .table { + background-color: #fff +} + +.table-sm td, +.table-sm th { + padding: .3rem +} + +.table-bordered, +.table-bordered td, +.table-bordered th { + border: 1px solid #e9ecef +} + +.table-bordered thead td, +.table-bordered thead th { + border-bottom-width: 2px +} + +.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(0, 0, 0, .05) +} + +.table-hover tbody tr:hover { + background-color: rgba(0, 0, 0, .075) +} + +.table-primary, +.table-primary>td, +.table-primary>th { + background-color: #b8daff +} + +.table-hover .table-primary:hover, +.table-hover .table-primary:hover>td, +.table-hover .table-primary:hover>th { + background-color: #9fcdff +} + +.table-secondary, +.table-secondary>td, +.table-secondary>th { + background-color: #dddfe2 +} + +.table-hover .table-secondary:hover, +.table-hover .table-secondary:hover>td, +.table-hover .table-secondary:hover>th { + background-color: #cfd2d6 +} + +.table-success, +.table-success>td, +.table-success>th { + background-color: #c3e6cb +} + +.table-hover .table-success:hover, +.table-hover .table-success:hover>td, +.table-hover .table-success:hover>th { + background-color: #b1dfbb +} + +.table-info, +.table-info>td, +.table-info>th { + background-color: #bee5eb +} + +.table-hover .table-info:hover, +.table-hover .table-info:hover>td, +.table-hover .table-info:hover>th { + background-color: #abdde5 +} + +.table-warning, +.table-warning>td, +.table-warning>th { + background-color: #ffeeba +} + +.table-hover .table-warning:hover, +.table-hover .table-warning:hover>td, +.table-hover .table-warning:hover>th { + background-color: #ffe8a1 +} + +.table-danger, +.table-danger>td, +.table-danger>th { + background-color: #f5c6cb +} + +.table-hover .table-danger:hover, +.table-hover .table-danger:hover>td, +.table-hover .table-danger:hover>th { + background-color: #f1b0b7 +} + +.table-light, +.table-light>td, +.table-light>th { + background-color: #fdfdfe +} + +.table-hover .table-light:hover, +.table-hover .table-light:hover>td, +.table-hover .table-light:hover>th { + background-color: #ececf6 +} + +.table-dark, +.table-dark>td, +.table-dark>th { + background-color: #c6c8ca +} + +.table-hover .table-dark:hover, +.table-hover .table-dark:hover>td, +.table-hover .table-dark:hover>th { + background-color: #b9bbbe +} + +.table-active, +.table-active>td, +.table-active>th, +.table-hover .table-active:hover, +.table-hover .table-active:hover>td, +.table-hover .table-active:hover>th { + background-color: rgba(0, 0, 0, .075) +} + +.table .thead-dark th { + color: #fff; + background-color: #212529; + border-color: #32383e +} + +.table .thead-light th { + color: #495057; + background-color: #e9ecef; + border-color: #e9ecef +} + +.table-dark { + color: #fff; + background-color: #212529 +} + +.table-dark td, +.table-dark th, +.table-dark thead th { + border-color: #32383e +} + +.table-dark.table-bordered, +.table-responsive.table-bordered { + border: 0 +} + +.table-dark.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(255, 255, 255, .05) +} + +.table-dark.table-hover tbody tr:hover { + background-color: rgba(255, 255, 255, .075) +} + +@media (max-width: 575px) { + .table-responsive-sm { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar + } + .table-responsive-sm.table-bordered { + border: 0 + } +} + +@media (max-width: 767px) { + .table-responsive-md { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar + } + .table-responsive-md.table-bordered { + border: 0 + } +} + +@media (max-width: 991px) { + .table-responsive-lg { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar + } + .table-responsive-lg.table-bordered { + border: 0 + } +} + +@media (max-width: 1199px) { + .table-responsive-xl { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar + } + .table-responsive-xl.table-bordered { + border: 0 + } +} + +.table-responsive { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar +} + +.collapsing, +.modal, +.modal-open { + overflow: hidden +} + +.form-control { + width: 100%; + color: #495057; + background-clip: padding-box; + border: 1px solid #ced4da; + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s +} + +.form-control::-ms-expand { + background-color: transparent; + border: 0 +} + +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #80bdff; + outline: 0 +} + +.form-control::-ms-input-placeholder { + color: #868e96; + opacity: 1 +} + +.form-control::-webkit-input-placeholder { + color: #868e96; + opacity: 1 +} + +.form-control::-moz-placeholder { + color: #868e96; + opacity: 1 +} + +.form-control:-ms-input-placeholder { + color: #868e96; + opacity: 1 +} + +.form-control::placeholder { + color: #868e96; + opacity: 1 +} + +.form-control:disabled, +.form-control[readonly] { + opacity: 1 +} + +select.form-control:not([size]):not([multiple]) { + height: -webkit-calc(2.25rem + 2px); + height: calc(2.25rem + 2px) +} + +select.form-control:focus::-ms-value { + color: #495057; + background-color: #fff +} + +.col-form-label { + padding-top: -webkit-calc(.375rem + 1px); + padding-top: calc(.375rem + 1px); + padding-bottom: -webkit-calc(.375rem + 1px); + padding-bottom: calc(.375rem + 1px); + margin-bottom: 0; + line-height: 1.5 +} + +.col-form-label-lg { + padding-top: -webkit-calc(.5rem + 1px); + padding-top: calc(.5rem + 1px); + padding-bottom: -webkit-calc(.5rem + 1px); + padding-bottom: calc(.5rem + 1px); + font-size: 1.25rem; + line-height: 1.5 +} + +.col-form-label-sm { + padding-top: -webkit-calc(.25rem + 1px); + padding-top: calc(.25rem + 1px); + padding-bottom: -webkit-calc(.25rem + 1px); + padding-bottom: calc(.25rem + 1px); + font-size: .875rem; + line-height: 1.5 +} + +.col-form-legend, +.form-control-plaintext { + padding-top: .375rem; + padding-bottom: .375rem; + margin-bottom: 0 +} + +.col-form-legend { + font-size: 1rem +} + +.form-control-plaintext { + line-height: 1.5; + background-color: transparent; + border: solid transparent; + border-width: 1px 0 +} + +.custom-file-input.is-valid~.custom-file-control, +.custom-select.is-valid, +.form-control.is-valid, +.was-validated .custom-file-input:valid~.custom-file-control, +.was-validated .custom-select:valid, +.was-validated .form-control:valid { + border-color: #28a745 +} + +.form-control-plaintext.form-control-lg, +.form-control-plaintext.form-control-sm, +.input-group-lg>.form-control-plaintext.form-control, +.input-group-lg>.form-control-plaintext.input-group-addon, +.input-group-lg>.input-group-btn>.form-control-plaintext.btn, +.input-group-sm>.form-control-plaintext.form-control, +.input-group-sm>.form-control-plaintext.input-group-addon, +.input-group-sm>.input-group-btn>.form-control-plaintext.btn { + padding-right: 0; + padding-left: 0 +} + +.form-control-sm, +.input-group-sm>.form-control, +.input-group-sm>.input-group-addon, +.input-group-sm>.input-group-btn>.btn { + padding: .25rem .5rem; + font-size: .875rem; + line-height: 1.5; + border-radius: .2rem +} + +.input-group-sm>.input-group-btn>select.btn:not([size]):not([multiple]), +.input-group-sm>select.form-control:not([size]):not([multiple]), +.input-group-sm>select.input-group-addon:not([size]):not([multiple]), +select.form-control-sm:not([size]):not([multiple]) { + height: -webkit-calc(1.8125rem + 2px); + height: calc(1.8125rem + 2px) +} + +.form-control-lg, +.input-group-lg>.form-control, +.input-group-lg>.input-group-addon, +.input-group-lg>.input-group-btn>.btn { + padding: .5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: .3rem +} + +.input-group-lg>.input-group-btn>select.btn:not([size]):not([multiple]), +.input-group-lg>select.form-control:not([size]):not([multiple]), +.input-group-lg>select.input-group-addon:not([size]):not([multiple]), +select.form-control-lg:not([size]):not([multiple]) { + height: -webkit-calc(2.875rem + 2px); + height: calc(2.875rem + 2px) +} + +.form-group { + margin-bottom: 1rem +} + +.form-row { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -5px; + margin-left: -5px +} + +.form-row>.col, +.form-row>[class*=col-] { + padding-right: 5px; + padding-left: 5px +} + +.form-check { + position: relative; + display: block; + margin-bottom: .5rem +} + +.form-check.disabled .form-check-label { + color: #868e96 +} + +.form-check-label { + padding-left: 1.25rem; + margin-bottom: 0 +} + +.invalid-tooltip, +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + width: 250px; + padding: .5rem; + line-height: 1; + border-radius: .2rem +} + +.form-check-input { + position: absolute; + margin-left: -1.25rem +} + +.form-check-inline { + display: inline-block; + margin-right: .75rem +} + +.valid-feedback, +.valid-tooltip { + display: none; + font-size: .875rem +} + +.form-check-inline .form-check-label { + vertical-align: middle +} + +.valid-feedback { + color: #28a745 +} + +.valid-tooltip { + margin-top: .1rem; + color: #fff; + background-color: rgba(40, 167, 69, .8) +} + +.custom-control-input.is-valid~.custom-control-description, +.form-check-input.is-valid+.form-check-label, +.was-validated .custom-control-input:valid~.custom-control-description, +.was-validated .form-check-input:valid+.form-check-label { + color: #28a745 +} + +.custom-select.is-valid:focus, +.form-control.is-valid:focus, +.was-validated .custom-select:valid:focus, +.was-validated .form-control:valid:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25); + box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25) +} + +.custom-select.is-valid~.valid-feedback, +.custom-select.is-valid~.valid-tooltip, +.form-control.is-valid~.valid-feedback, +.form-control.is-valid~.valid-tooltip, +.was-validated .custom-select:valid~.valid-feedback, +.was-validated .custom-select:valid~.valid-tooltip, +.was-validated .form-control:valid~.valid-feedback, +.was-validated .form-control:valid~.valid-tooltip { + display: block +} + +.custom-control-input.is-valid~.custom-control-indicator, +.was-validated .custom-control-input:valid~.custom-control-indicator { + background-color: rgba(40, 167, 69, .25) +} + +.custom-file-input.is-valid~.custom-file-control::before, +.was-validated .custom-file-input:valid~.custom-file-control::before { + border-color: inherit +} + +.custom-file-input.is-invalid~.custom-file-control, +.custom-select.is-invalid, +.form-control.is-invalid, +.was-validated .custom-file-input:invalid~.custom-file-control, +.was-validated .custom-select:invalid, +.was-validated .form-control:invalid { + border-color: #dc3545 +} + +.custom-file-input.is-valid:focus, +.was-validated .custom-file-input:valid:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25); + box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .25) +} + +.invalid-feedback { + display: none; + margin-top: .25rem; + font-size: .875rem; + color: #dc3545 +} + +.invalid-tooltip { + display: none; + margin-top: .1rem; + font-size: .875rem; + color: #fff; + background-color: rgba(220, 53, 69, .8) +} + +.custom-control-input.is-invalid~.custom-control-description, +.form-check-input.is-invalid+.form-check-label, +.was-validated .custom-control-input:invalid~.custom-control-description, +.was-validated .form-check-input:invalid+.form-check-label { + color: #dc3545 +} + +.custom-select.is-invalid:focus, +.form-control.is-invalid:focus, +.was-validated .custom-select:invalid:focus, +.was-validated .form-control:invalid:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25); + box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25) +} + +.custom-select.is-invalid~.invalid-feedback, +.custom-select.is-invalid~.invalid-tooltip, +.form-control.is-invalid~.invalid-feedback, +.form-control.is-invalid~.invalid-tooltip, +.was-validated .custom-select:invalid~.invalid-feedback, +.was-validated .custom-select:invalid~.invalid-tooltip, +.was-validated .form-control:invalid~.invalid-feedback, +.was-validated .form-control:invalid~.invalid-tooltip { + display: block +} + +.custom-control-input.is-invalid~.custom-control-indicator, +.was-validated .custom-control-input:invalid~.custom-control-indicator { + background-color: rgba(220, 53, 69, .25) +} + +.custom-file-input.is-invalid~.custom-file-control::before, +.was-validated .custom-file-input:invalid~.custom-file-control::before { + border-color: inherit +} + +.custom-file-input.is-invalid:focus, +.was-validated .custom-file-input:invalid:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25); + box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .25) +} + +.form-inline { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-flow: row wrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-flow: row wrap; + flex-flow: row wrap; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center +} + +.form-inline .form-check { + width: 100% +} + +@media (min-width: 576px) { + .form-inline label { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + margin-bottom: 0 + } + .form-inline .form-check, + .form-inline .form-group { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + margin-bottom: 0 + } + .form-inline .form-group { + display: flex; + -ms-flex: 0 0 auto; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + flex: 0 0 auto; + -ms-flex-flow: row wrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-flow: row wrap; + flex-flow: row wrap; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle + } + .form-inline .form-control-plaintext { + display: inline-block + } + .form-inline .input-group { + width: auto + } + .form-inline .form-check { + display: flex; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + width: auto; + margin-top: 0 + } + .form-inline .form-check-label { + padding-left: 0 + } + .form-inline .form-check-input { + position: relative; + margin-top: 0; + margin-right: .25rem; + margin-left: 0 + } + .form-inline .custom-control { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + padding-left: 0 + } + .form-inline .custom-control-indicator { + position: static; + display: inline-block; + margin-right: .25rem; + vertical-align: text-bottom + } + .form-inline .has-feedback .form-control-feedback { + top: 0 + } +} + +.btn-group-vertical, +.custom-controls-stacked { + -webkit-box-orient: vertical; + -webkit-box-direction: normal +} + +.btn-block, +input[type=button].btn-block, +input[type=reset].btn-block, +input[type=submit].btn-block { + width: 100% +} + +.collapsing, +.dropdown, +.dropup { + position: relative +} + +.btn { + display: inline-block; + text-align: center; + vertical-align: middle; + user-select: none; + line-height: 1.5 +} + +.btn:focus, +.btn:hover { + text-decoration: none +} + +.btn.focus, +.btn:focus { + outline: 0; + -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25); + box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25) +} + +.btn.disabled, +.btn:disabled { + opacity: .65 +} + +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none +} + +.btn-primary { + color: #fff; + border-color: #007bff +} + +.btn-primary:hover { + color: #fff; + border-color: #0062cc +} + +.btn-primary.focus, +.btn-primary:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5); + box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5) +} + +.btn-primary.disabled, +.btn-primary:disabled { + background-color: #007bff; + border-color: #007bff +} + +.btn-primary:not([disabled]):not(.disabled).active, +.btn-primary:not([disabled]):not(.disabled):active, +.show>.btn-primary.dropdown-toggle { + color: #fff; + background-color: #0062cc; + border-color: #005cbf; + -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5); + box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5) +} + +.btn-secondary { + color: #fff; + border-color: #868e96 +} + +.btn-secondary:hover { + color: #fff; + border-color: #6c757d +} + +.btn-secondary.focus, +.btn-secondary:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5); + box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5) +} + +.btn-secondary:not([disabled]):not(.disabled).active, +.btn-secondary:not([disabled]):not(.disabled):active, +.show>.btn-secondary.dropdown-toggle { + color: #fff; + background-color: #6c757d; + border-color: #666e76; + -webkit-box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5); + box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5) +} + +.btn-success { + color: #fff; + border-color: #28a745 +} + +.btn-success:hover { + color: #fff; + border-color: #1e7e34 +} + +.btn-success.focus, +.btn-success:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5); + box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5) +} + +.btn-success.disabled, +.btn-success:disabled { + background-color: #28a745; + border-color: #28a745 +} + +.btn-success:not([disabled]):not(.disabled).active, +.btn-success:not([disabled]):not(.disabled):active, +.show>.btn-success.dropdown-toggle { + color: #fff; + background-color: #1e7e34; + border-color: #1c7430; + -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5); + box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5) +} + +.btn-info { + color: #fff; + border-color: #17a2b8 +} + +.btn-info:hover { + color: #fff; + border-color: #117a8b +} + +.btn-info.focus, +.btn-info:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5); + box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5) +} + +.btn-info.disabled, +.btn-info:disabled { + background-color: #17a2b8; + border-color: #17a2b8 +} + +.btn-info:not([disabled]):not(.disabled).active, +.btn-info:not([disabled]):not(.disabled):active, +.show>.btn-info.dropdown-toggle { + color: #fff; + background-color: #117a8b; + border-color: #10707f; + -webkit-box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5); + box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5) +} + +.btn-warning { + color: #111; + border-color: #ffc107 +} + +.btn-warning:hover { + color: #111; + border-color: #d39e00 +} + +.btn-warning.focus, +.btn-warning:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5); + box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5) +} + +.btn-warning.disabled, +.btn-warning:disabled { + background-color: #ffc107; + border-color: #ffc107 +} + +.btn-warning:not([disabled]):not(.disabled).active, +.btn-warning:not([disabled]):not(.disabled):active, +.show>.btn-warning.dropdown-toggle { + color: #111; + background-color: #d39e00; + border-color: #c69500; + -webkit-box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5); + box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5) +} + +.btn-danger { + color: #fff; + border-color: #dc3545 +} + +.btn-danger:hover { + color: #fff; + border-color: #bd2130 +} + +.btn-danger.focus, +.btn-danger:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5); + box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5) +} + +.btn-danger.disabled, +.btn-danger:disabled { + background-color: #dc3545; + border-color: #dc3545 +} + +.btn-danger:not([disabled]):not(.disabled).active, +.btn-danger:not([disabled]):not(.disabled):active, +.show>.btn-danger.dropdown-toggle { + color: #fff; + background-color: #bd2130; + border-color: #b21f2d; + -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5); + box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5) +} + +.btn-light { + color: #111; + background-color: #f8f9fa; + border-color: #f8f9fa +} + +.btn-light:hover { + color: #111; + background-color: #e2e6ea; + border-color: #dae0e5 +} + +.btn-light.focus, +.btn-light:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5); + box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5) +} + +.btn-light.disabled, +.btn-light:disabled { + background-color: #f8f9fa; + border-color: #f8f9fa +} + +.btn-light:not([disabled]):not(.disabled).active, +.btn-light:not([disabled]):not(.disabled):active, +.show>.btn-light.dropdown-toggle { + color: #111; + background-color: #dae0e5; + border-color: #d3d9df; + -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5); + box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5) +} + +.btn-dark { + color: #fff; + background-color: #343a40; + border-color: #343a40 +} + +.btn-dark:hover { + color: #fff; + background-color: #23272b; + border-color: #1d2124 +} + +.btn-dark.focus, +.btn-dark:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5); + box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5) +} + +.btn-dark.disabled, +.btn-dark:disabled { + background-color: #343a40; + border-color: #343a40 +} + +.btn-dark:not([disabled]):not(.disabled).active, +.btn-dark:not([disabled]):not(.disabled):active, +.show>.btn-dark.dropdown-toggle { + color: #fff; + background-color: #1d2124; + border-color: #171a1d; + -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5); + box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5) +} + +.btn-outline-primary.focus, +.btn-outline-primary:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5); + box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5) +} + +.btn-outline-primary.disabled, +.btn-outline-primary:disabled { + color: #007bff; + background-color: transparent +} + +.btn-outline-primary:not([disabled]):not(.disabled).active, +.btn-outline-primary:not([disabled]):not(.disabled):active, +.show>.btn-outline-primary.dropdown-toggle { + color: #fff; + background-color: #007bff; + border-color: #007bff; + -webkit-box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5); + box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .5) +} + +.btn-outline-secondary.focus, +.btn-outline-secondary:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5); + box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5) +} + +.btn-outline-secondary.disabled, +.btn-outline-secondary:disabled { + color: #868e96; + background-color: transparent +} + +.btn-outline-secondary:not([disabled]):not(.disabled).active, +.btn-outline-secondary:not([disabled]):not(.disabled):active, +.show>.btn-outline-secondary.dropdown-toggle { + color: #fff; + background-color: #868e96; + border-color: #868e96; + -webkit-box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5); + box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5) +} + +.btn-outline-success.focus, +.btn-outline-success:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5); + box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5) +} + +.btn-outline-success.disabled, +.btn-outline-success:disabled { + color: #28a745; + background-color: transparent +} + +.btn-outline-success:not([disabled]):not(.disabled).active, +.btn-outline-success:not([disabled]):not(.disabled):active, +.show>.btn-outline-success.dropdown-toggle { + color: #fff; + background-color: #28a745; + border-color: #28a745; + -webkit-box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5); + box-shadow: 0 0 0 .2rem rgba(40, 167, 69, .5) +} + +.btn-outline-info.focus, +.btn-outline-info:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5); + box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5) +} + +.btn-outline-info.disabled, +.btn-outline-info:disabled { + color: #17a2b8; + background-color: transparent +} + +.btn-outline-info:not([disabled]):not(.disabled).active, +.btn-outline-info:not([disabled]):not(.disabled):active, +.show>.btn-outline-info.dropdown-toggle { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; + -webkit-box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5); + box-shadow: 0 0 0 .2rem rgba(23, 162, 184, .5) +} + +.btn-outline-warning.focus, +.btn-outline-warning:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5); + box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5) +} + +.btn-outline-warning.disabled, +.btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent +} + +.btn-outline-warning:not([disabled]):not(.disabled).active, +.btn-outline-warning:not([disabled]):not(.disabled):active, +.show>.btn-outline-warning.dropdown-toggle { + color: #fff; + background-color: #ffc107; + border-color: #ffc107; + -webkit-box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5); + box-shadow: 0 0 0 .2rem rgba(255, 193, 7, .5) +} + +.btn-outline-danger.focus, +.btn-outline-danger:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5); + box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5) +} + +.btn-outline-danger.disabled, +.btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent +} + +.btn-outline-danger:not([disabled]):not(.disabled).active, +.btn-outline-danger:not([disabled]):not(.disabled):active, +.show>.btn-outline-danger.dropdown-toggle { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; + -webkit-box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5); + box-shadow: 0 0 0 .2rem rgba(220, 53, 69, .5) +} + +.btn-outline-light { + color: #f8f9fa; + background-color: transparent; + border-color: #f8f9fa +} + +.btn-outline-light:hover { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa +} + +.btn-outline-light.focus, +.btn-outline-light:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5); + box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5) +} + +.btn-outline-light.disabled, +.btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent +} + +.btn-outline-light:not([disabled]):not(.disabled).active, +.btn-outline-light:not([disabled]):not(.disabled):active, +.show>.btn-outline-light.dropdown-toggle { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; + -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5); + box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5) +} + +.btn-outline-dark { + color: #343a40; + background-color: transparent; + border-color: #343a40 +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #343a40; + border-color: #343a40 +} + +.btn-outline-dark.focus, +.btn-outline-dark:focus { + -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5); + box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5) +} + +.btn-outline-dark.disabled, +.btn-outline-dark:disabled { + color: #343a40; + background-color: transparent +} + +.btn-outline-dark:not([disabled]):not(.disabled).active, +.btn-outline-dark:not([disabled]):not(.disabled):active, +.show>.btn-outline-dark.dropdown-toggle { + color: #fff; + background-color: #343a40; + border-color: #343a40; + -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5); + box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5) +} + +.btn-link:hover { + color: #0056b3; + text-decoration: underline; + border-color: transparent +} + +.btn-link.focus, +.btn-link:focus { + border-color: transparent; + -webkit-box-shadow: none; + box-shadow: none +} + +.btn-link.disabled, +.btn-link:disabled { + color: #868e96 +} + +.btn-group-lg>.btn, +.btn-lg { + padding: .5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: .3rem +} + +.btn-group-sm>.btn, +.btn-sm { + padding: .25rem .5rem; + font-size: .875rem; + line-height: 1.5; + border-radius: .2rem +} + +.btn-block { + display: block +} + +.btn-block+.btn-block { + margin-top: .5rem +} + +.dropdown-toggle::after, +.dropup .dropdown-toggle::after { + width: 0; + vertical-align: .255em; + content: ""; + height: 0 +} + +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + transition: opacity .15s linear +} + +.fade.show { + opacity: 1 +} + +.collapse { + display: none +} + +.collapse.show { + display: block +} + +tr.collapse.show { + display: table-row +} + +tbody.collapse.show { + display: table-row-group +} + +.collapsing { + height: 0; + -webkit-transition: height .35s ease; + transition: height .35s ease +} + +.dropdown-toggle::after { + display: inline-block; + margin-left: .255em; + border-top: .3em solid; + border-right: .3em solid transparent; + border-bottom: 0; + border-left: .3em solid transparent +} + +.dropdown-toggle:empty::after { + margin-left: 0 +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 10rem; + padding: .5rem 0; + margin: .125rem 0 0; + font-size: 1rem; + color: #212529; + text-align: left; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: .25rem +} + +.dropup .dropdown-menu { + margin-top: 0; + margin-bottom: .125rem +} + +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: .255em; + border-top: 0; + border-right: .3em solid transparent; + border-bottom: .3em solid; + border-left: .3em solid transparent +} + +.dropup .dropdown-toggle:empty::after { + margin-left: 0 +} + +.dropdown-divider { + height: 0; + margin: .5rem 0; + overflow: hidden; + border-top: 1px solid #e9ecef +} + +.dropdown-item { + display: block; + width: 100%; + padding: .25rem 1.5rem; + clear: both; + color: #212529; + text-align: inherit; + white-space: nowrap; + background: 0 0; + border: 0 +} + +.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn, +.btn-group-vertical>.btn:not(:first-child):not(:last-child), +.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn, +.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle), +.input-group .form-control:not(:first-child):not(:last-child), +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child) { + border-radius: 0 +} + +.dropdown-item:focus, +.dropdown-item:hover { + color: #16181b; + text-decoration: none; + background-color: #f8f9fa +} + +.dropdown-item.active, +.dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #007bff +} + +.dropdown-item.disabled, +.dropdown-item:disabled { + color: #868e96; + background-color: transparent +} + +.dropdown-menu.show { + display: block +} + +.dropdown-header { + display: block; + padding: .5rem 1.5rem; + margin-bottom: 0; + font-size: .875rem; + color: #868e96; + white-space: nowrap +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: -ms-inline-flexbox; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: inline-flex; + vertical-align: middle +} + +.btn-toolbar, +.input-group { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex +} + +.btn-group-vertical>.btn, +.btn-group>.btn { + position: relative; + -ms-flex: 0 1 auto; + -webkit-box-flex: 0; + -webkit-flex: 0 1 auto; + flex: 0 1 auto +} + +.btn-group-vertical>.btn.active, +.btn-group-vertical>.btn:active, +.btn-group-vertical>.btn:focus, +.btn-group-vertical>.btn:hover, +.btn-group>.btn.active, +.btn-group>.btn:active, +.btn-group>.btn:focus, +.btn-group>.btn:hover { + z-index: 2 +} + +.btn-group .btn+.btn, +.btn-group .btn+.btn-group, +.btn-group .btn-group+.btn, +.btn-group .btn-group+.btn-group, +.btn-group-vertical .btn+.btn, +.btn-group-vertical .btn+.btn-group, +.btn-group-vertical .btn-group+.btn, +.btn-group-vertical .btn-group+.btn-group { + margin-left: -1px +} + +.btn+.dropdown-toggle-split::after, +.btn-group>.btn:first-child { + margin-left: 0 +} + +.btn-toolbar { + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-pack: start; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start +} + +.btn-toolbar .input-group { + width: auto +} + +.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.btn-group>.btn:last-child:not(:first-child), +.btn-group>.dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.btn-group>.btn-group { + float: left +} + +.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child, +.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.btn+.dropdown-toggle-split { + padding-right: .5625rem; + padding-left: .5625rem +} + +.btn-group-sm>.btn+.dropdown-toggle-split, +.btn-sm+.dropdown-toggle-split { + padding-right: .375rem; + padding-left: .375rem +} + +.btn-group-lg>.btn+.dropdown-toggle-split, +.btn-lg+.dropdown-toggle-split { + padding-right: .75rem; + padding-left: .75rem +} + +.btn-group-vertical { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex-align: start; + -webkit-box-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + -ms-flex-pack: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center +} + +.btn-group-vertical .btn, +.btn-group-vertical .btn-group { + width: 100% +} + +.btn-group-vertical>.btn+.btn, +.btn-group-vertical>.btn+.btn-group, +.btn-group-vertical>.btn-group+.btn, +.btn-group-vertical>.btn-group+.btn-group { + margin-top: -1px; + margin-left: 0 +} + +.btn-group-vertical>.btn:first-child:not(:last-child) { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0 +} + +.btn-group-vertical>.btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child, +.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0 +} + +.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +[data-toggle=buttons]>.btn input[type=radio], +[data-toggle=buttons]>.btn input[type=checkbox], +[data-toggle=buttons]>.btn-group>.btn input[type=radio], +[data-toggle=buttons]>.btn-group>.btn input[type=checkbox] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none +} + +.custom-control, +.input-group, +.input-group-btn, +.input-group-btn>.btn { + position: relative +} + +.input-group { + display: flex; + -ms-flex-align: stretch; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + align-items: stretch; + width: 100% +} + +.input-group .form-control { + position: relative; + z-index: 2; + -ms-flex: 1 1 auto; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + width: 1%; + margin-bottom: 0 +} + +.input-group .form-control:active, +.input-group .form-control:focus, +.input-group .form-control:hover, +.input-group-btn>.btn:active, +.input-group-btn>.btn:focus, +.input-group-btn>.btn:hover { + z-index: 3 +} + +.input-group .form-control, +.input-group-addon, +.input-group-btn { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center +} + +.input-group-addon, +.input-group-btn { + white-space: nowrap +} + +.input-group-addon { + padding: .375rem .75rem; + margin-bottom: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + text-align: center; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: .25rem +} + +.input-group-addon.form-control-sm, +.input-group-sm>.input-group-addon, +.input-group-sm>.input-group-btn>.input-group-addon.btn { + padding: .25rem .5rem; + font-size: .875rem; + border-radius: .2rem +} + +.input-group-addon.form-control-lg, +.input-group-lg>.input-group-addon, +.input-group-lg>.input-group-btn>.input-group-addon.btn { + padding: .5rem 1rem; + font-size: 1.25rem; + border-radius: .3rem +} + +.input-group-addon input[type=radio], +.input-group-addon input[type=checkbox] { + margin-top: 0 +} + +.input-group .form-control:not(:last-child), +.input-group-addon:not(:last-child), +.input-group-btn:not(:first-child)>.btn-group:not(:last-child)>.btn, +.input-group-btn:not(:first-child)>.btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:not(:last-child)>.btn, +.input-group-btn:not(:last-child)>.btn-group>.btn, +.input-group-btn:not(:last-child)>.dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.input-group-addon:not(:last-child) { + border-right: 0 +} + +.input-group .form-control:not(:first-child), +.input-group-addon:not(:first-child), +.input-group-btn:not(:first-child)>.btn, +.input-group-btn:not(:first-child)>.btn-group>.btn, +.input-group-btn:not(:first-child)>.dropdown-toggle, +.input-group-btn:not(:last-child)>.btn-group:not(:first-child)>.btn, +.input-group-btn:not(:last-child)>.btn:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.form-control+.input-group-addon:not(:first-child) { + border-left: 0 +} + +.input-group-btn { + -ms-flex-align: stretch; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + align-items: stretch; + font-size: 0; + white-space: nowrap +} + +.input-group-btn>.btn+.btn { + margin-left: -1px +} + +.input-group-btn:first-child>.btn+.btn { + margin-left: 0 +} + +.input-group-btn:not(:last-child)>.btn, +.input-group-btn:not(:last-child)>.btn-group { + margin-right: -1px +} + +.input-group-btn:not(:first-child)>.btn, +.input-group-btn:not(:first-child)>.btn-group { + z-index: 2; + margin-left: 0 +} + +.input-group-btn:not(:first-child)>.btn-group:first-child, +.input-group-btn:not(:first-child)>.btn:first-child { + margin-left: -1px +} + +.card>hr, +.custom-controls-stacked .custom-control+.custom-control { + margin-left: 0 +} + +.input-group-btn:not(:first-child)>.btn-group:active, +.input-group-btn:not(:first-child)>.btn-group:focus, +.input-group-btn:not(:first-child)>.btn-group:hover, +.input-group-btn:not(:first-child)>.btn:active, +.input-group-btn:not(:first-child)>.btn:focus, +.input-group-btn:not(:first-child)>.btn:hover { + z-index: 3 +} + +.custom-control { + display: -ms-inline-flexbox; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: inline-flex; + min-height: 1.5rem; + padding-left: 1.5rem; + margin-right: 1rem +} + +.custom-control-input { + position: absolute; + z-index: -1; + opacity: 0 +} + +.custom-control-input:checked~.custom-control-indicator { + color: #fff; + background-color: #007bff +} + +.custom-control-input:focus~.custom-control-indicator { + -webkit-box-shadow: 0 0 0 1px #fff, 0 0 0 .2rem rgba(0, 123, 255, .25); + box-shadow: 0 0 0 1px #fff, 0 0 0 .2rem rgba(0, 123, 255, .25) +} + +.custom-control-input:active~.custom-control-indicator { + color: #fff; + background-color: #b3d7ff +} + +.custom-control-input:disabled~.custom-control-indicator { + background-color: #e9ecef +} + +.custom-control-input:disabled~.custom-control-description { + color: #868e96 +} + +.custom-control-indicator { + position: absolute; + top: .25rem; + left: 0; + display: block; + width: 1rem; + height: 1rem; + pointer-events: none; + user-select: none; + background-color: #ddd; + background-repeat: no-repeat; + background-position: center center; + background-size: 50% 50% +} + +.custom-file-control, +.waves-effect { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none +} + +.custom-checkbox .custom-control-indicator { + border-radius: .25rem +} + +.custom-checkbox .custom-control-input:checked~.custom-control-indicator { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") +} + +.custom-checkbox .custom-control-input:indeterminate~.custom-control-indicator { + background-color: #007bff; + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E") +} + +.custom-radio .custom-control-indicator { + border-radius: 50% +} + +.custom-radio .custom-control-input:checked~.custom-control-indicator { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E") +} + +.custom-controls-stacked { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column +} + +.custom-file, +.custom-select { + display: inline-block; + height: -webkit-calc(2.25rem + 2px); + max-width: 100% +} + +.custom-controls-stacked .custom-control { + margin-bottom: .25rem +} + +.custom-select { + height: calc(2.25rem + 2px); + padding: .375rem 1.75rem .375rem .75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center no-repeat #fff; + background-size: 8px 10px; + border: 1px solid #ced4da; + border-radius: .25rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +.pswp__button, +[type=reset], +[type=submit], +button, +button.close, +html [type=button], +input[type=range] { + -webkit-appearance: none +} + +.custom-select:focus { + border-color: #80bdff; + outline: 0 +} + +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff +} + +.custom-select[multiple] { + height: auto; + background-image: none +} + +.custom-select:disabled { + color: #868e96; + background-color: #e9ecef +} + +.custom-select::-ms-expand { + opacity: 0 +} + +.custom-select-sm { + height: -webkit-calc(1.8125rem + 2px); + height: calc(1.8125rem + 2px); + padding-top: .375rem; + padding-bottom: .375rem; + font-size: 75% +} + +.custom-file { + position: relative; + height: calc(2.25rem + 2px); + margin-bottom: 0 +} + +.custom-file-control, +.custom-file-control::before { + position: absolute; + padding: .375rem .75rem; + line-height: 1.5; + color: #495057 +} + +.custom-file-input { + min-width: 14rem; + max-width: 100%; + height: -webkit-calc(2.25rem + 2px); + height: calc(2.25rem + 2px); + margin: 0; + opacity: 0 +} + +.custom-file-input:focus~.custom-file-control { + -webkit-box-shadow: 0 0 0 .075rem #fff, 0 0 0 .2rem #007bff; + box-shadow: 0 0 0 .075rem #fff, 0 0 0 .2rem #007bff +} + +.custom-file-control { + top: 0; + right: 0; + left: 0; + z-index: 5; + height: -webkit-calc(2.25rem + 2px); + height: calc(2.25rem + 2px); + pointer-events: none; + user-select: none; + background-color: #fff; + border: 1px solid #ced4da; + border-radius: .25rem +} + +.custom-file-control:lang(en):empty::after { + content: "Choose file..." +} + +.custom-file-control::before { + top: -1px; + right: -1px; + bottom: -1px; + z-index: 6; + display: block; + height: -webkit-calc(2.25rem + 2px); + height: calc(2.25rem + 2px); + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: 0 .25rem .25rem 0 +} + +.nav, +.navbar { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + -ms-flex-wrap: wrap +} + +.custom-file-control:lang(en)::before { + content: "Browse" +} + +.nav { + display: flex; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0 +} + +.nav-link, +.navbar { + padding: .5rem 1rem +} + +.nav-link { + display: block +} + +.nav-link:focus, +.nav-link:hover { + text-decoration: none +} + +.nav-link.disabled { + color: #868e96 +} + +.nav-tabs .nav-item { + margin-bottom: -1px +} + +.nav-tabs .nav-link { + border-top-left-radius: .25rem; + border-top-right-radius: .25rem +} + +.nav-tabs .nav-link:focus, +.nav-tabs .nav-link:hover { + border-color: #e9ecef #e9ecef #ddd +} + +.nav-tabs .nav-link.disabled { + color: #868e96; + background-color: transparent; + border-color: transparent +} + +.nav-tabs .nav-item.show .nav-link, +.nav-tabs .nav-link.active { + color: #495057; + background-color: #fff; + border-color: #ddd #ddd #fff +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.nav-pills .nav-link { + border-radius: .25rem +} + +.nav-pills .nav-link.active, +.nav-pills .show>.nav-link { + color: #fff; + background-color: #007bff +} + +.nav-fill .nav-item { + -ms-flex: 1 1 auto; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + text-align: center +} + +.nav-justified .nav-item { + -ms-flex-preferred-size: 0; + -webkit-flex-basis: 0; + flex-basis: 0; + -ms-flex-positive: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + text-align: center +} + +.tab-content>.tab-pane { + display: none +} + +.tab-content>.active { + display: block +} + +.navbar { + position: relative; + display: flex; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: justify; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between +} + +.navbar>.container, +.navbar>.container-fluid { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: justify; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between +} + +.navbar-brand { + display: inline-block; + padding-top: .3125rem; + padding-bottom: .3125rem; + margin-right: 1rem; + font-size: 1.25rem; + line-height: inherit; + white-space: nowrap +} + +.card, +.navbar-nav { + display: -webkit-box; + -webkit-box-orient: vertical +} + +.navbar-brand:focus, +.navbar-brand:hover { + text-decoration: none +} + +.navbar-nav { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: column; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + flex-direction: column; + padding-left: 0; + margin-bottom: 0 +} + +.navbar-expand, +.navbar-expand .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal +} + +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0 +} + +.navbar-nav .dropdown-menu { + position: static; + float: none +} + +.navbar-text { + display: inline-block; + padding-top: .5rem; + padding-bottom: .5rem +} + +.navbar-collapse { + -ms-flex-preferred-size: 100%; + -webkit-flex-basis: 100%; + flex-basis: 100%; + -ms-flex-positive: 1; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + flex-grow: 1; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center +} + +.navbar-toggler { + padding: .25rem .75rem; + font-size: 1.25rem; + line-height: 1; + background: 0 0; + border: 1px solid transparent +} + +.navbar-toggler:focus, +.navbar-toggler:hover { + text-decoration: none +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + content: ""; + background: center center no-repeat; + background-size: 100% 100% +} + +@media (max-width: 575px) { + .navbar-expand-sm>.container, + .navbar-expand-sm>.container-fluid { + padding-right: 0; + padding-left: 0 + } +} + +@media (min-width: 576px) { + .navbar-expand-sm, + .navbar-expand-sm .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal + } + .navbar-expand-sm { + -ms-flex-flow: row nowrap; + -webkit-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start + } + .navbar-expand-sm .navbar-nav { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute + } + .navbar-expand-sm .navbar-nav .dropdown-menu-right { + right: 0; + left: auto + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + .navbar-expand-sm>.container, + .navbar-expand-sm>.container-fluid { + -ms-flex-wrap: nowrap; + -webkit-flex-wrap: nowrap; + flex-wrap: nowrap + } + .navbar-expand-sm .navbar-collapse { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important; + -ms-flex-preferred-size: auto; + -webkit-flex-basis: auto; + flex-basis: auto + } + .navbar-expand-sm .navbar-toggler { + display: none + } + .navbar-expand-sm .dropup .dropdown-menu { + top: auto; + bottom: 100% + } +} + +@media (max-width: 767px) { + .navbar-expand-md>.container, + .navbar-expand-md>.container-fluid { + padding-right: 0; + padding-left: 0 + } +} + +@media (min-width: 768px) { + .navbar-expand-md, + .navbar-expand-md .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal + } + .navbar-expand-md { + -ms-flex-flow: row nowrap; + -webkit-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start + } + .navbar-expand-md .navbar-nav { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute + } + .navbar-expand-md .navbar-nav .dropdown-menu-right { + right: 0; + left: auto + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + .navbar-expand-md>.container, + .navbar-expand-md>.container-fluid { + -ms-flex-wrap: nowrap; + -webkit-flex-wrap: nowrap; + flex-wrap: nowrap + } + .navbar-expand-md .navbar-collapse { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important; + -ms-flex-preferred-size: auto; + -webkit-flex-basis: auto; + flex-basis: auto + } + .navbar-expand-md .navbar-toggler { + display: none + } + .navbar-expand-md .dropup .dropdown-menu { + top: auto; + bottom: 100% + } +} + +@media (max-width: 991px) { + .navbar-expand-lg>.container, + .navbar-expand-lg>.container-fluid { + padding-right: 0; + padding-left: 0 + } +} + +@media (min-width: 992px) { + .navbar-expand-lg, + .navbar-expand-lg .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal + } + .navbar-expand-lg { + -ms-flex-flow: row nowrap; + -webkit-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start + } + .navbar-expand-lg .navbar-nav { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute + } + .navbar-expand-lg .navbar-nav .dropdown-menu-right { + right: 0; + left: auto + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + .navbar-expand-lg>.container, + .navbar-expand-lg>.container-fluid { + -ms-flex-wrap: nowrap; + -webkit-flex-wrap: nowrap; + flex-wrap: nowrap + } + .navbar-expand-lg .navbar-collapse { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important; + -ms-flex-preferred-size: auto; + -webkit-flex-basis: auto; + flex-basis: auto + } + .navbar-expand-lg .navbar-toggler { + display: none + } + .navbar-expand-lg .dropup .dropdown-menu { + top: auto; + bottom: 100% + } +} + +@media (max-width: 1199px) { + .navbar-expand-xl>.container, + .navbar-expand-xl>.container-fluid { + padding-right: 0; + padding-left: 0 + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl, + .navbar-expand-xl .navbar-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal + } + .navbar-expand-xl { + -ms-flex-flow: row nowrap; + -webkit-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start + } + .navbar-expand-xl .navbar-nav { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute + } + .navbar-expand-xl .navbar-nav .dropdown-menu-right { + right: 0; + left: auto + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + .navbar-expand-xl>.container, + .navbar-expand-xl>.container-fluid { + -ms-flex-wrap: nowrap; + -webkit-flex-wrap: nowrap; + flex-wrap: nowrap + } + .navbar-expand-xl .navbar-collapse { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important; + -ms-flex-preferred-size: auto; + -webkit-flex-basis: auto; + flex-basis: auto + } + .navbar-expand-xl .navbar-toggler { + display: none + } + .navbar-expand-xl .dropup .dropdown-menu { + top: auto; + bottom: 100% + } +} + +.navbar-expand { + -ms-flex-flow: row nowrap; + -webkit-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start +} + +.navbar-expand>.container, +.navbar-expand>.container-fluid { + padding-right: 0; + padding-left: 0 +} + +.navbar-expand .navbar-nav { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute +} + +.navbar-expand .navbar-nav .dropdown-menu-right { + right: 0; + left: auto +} + +.navbar-expand .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem +} + +.navbar-expand>.container, +.navbar-expand>.container-fluid { + -ms-flex-wrap: nowrap; + -webkit-flex-wrap: nowrap; + flex-wrap: nowrap +} + +.navbar-expand .navbar-collapse { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important; + -ms-flex-preferred-size: auto; + -webkit-flex-basis: auto; + flex-basis: auto +} + +.navbar-expand .navbar-toggler { + display: none +} + +.navbar-expand .dropup .dropdown-menu { + top: auto; + bottom: 100% +} + +.modal, +.modal-backdrop, +.popover.bs-popover-auto[x-placement^=top] .arrow, +.popover.bs-popover-top .arrow, +.tooltip.bs-tooltip-auto[x-placement^=top] .arrow, +.tooltip.bs-tooltip-top .arrow { + bottom: 0 +} + +.navbar-light .navbar-brand, +.navbar-light .navbar-brand:focus, +.navbar-light .navbar-brand:hover { + color: rgba(0, 0, 0, .9) +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, .5) +} + +.navbar-light .navbar-nav .nav-link:focus, +.navbar-light .navbar-nav .nav-link:hover { + color: rgba(0, 0, 0, .7) +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, .3) +} + +.navbar-light .navbar-nav .active>.nav-link, +.navbar-light .navbar-nav .nav-link.active, +.navbar-light .navbar-nav .nav-link.show, +.navbar-light .navbar-nav .show>.nav-link { + color: rgba(0, 0, 0, .9) +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, .5); + border-color: rgba(0, 0, 0, .1) +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E") +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, .5) +} + +.navbar-light .navbar-text a, +.navbar-light .navbar-text a:focus, +.navbar-light .navbar-text a:hover { + color: rgba(0, 0, 0, .9) +} + +.navbar-dark .navbar-brand, +.navbar-dark .navbar-brand:focus, +.navbar-dark .navbar-brand:hover { + color: #fff +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, .5) +} + +.navbar-dark .navbar-nav .nav-link:focus, +.navbar-dark .navbar-nav .nav-link:hover { + color: rgba(255, 255, 255, .75) +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, .25) +} + +.navbar-dark .navbar-nav .active>.nav-link, +.navbar-dark .navbar-nav .nav-link.active, +.navbar-dark .navbar-nav .nav-link.show, +.navbar-dark .navbar-nav .show>.nav-link { + color: #fff +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, .5); + border-color: rgba(255, 255, 255, .1) +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E") +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, .5) +} + +.navbar-dark .navbar-text a, +.navbar-dark .navbar-text a:focus, +.navbar-dark .navbar-text a:hover { + color: #fff +} + +.card { + position: relative; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: column; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, .125) +} + +.card>hr { + margin-right: 0 +} + +.card>.list-group:first-child .list-group-item:first-child { + border-top-left-radius: .25rem; + border-top-right-radius: .25rem +} + +.card>.list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: .25rem; + border-bottom-left-radius: .25rem +} + +.card-body { + -ms-flex: 1 1 auto; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1.25rem +} + +.card-footer, +.card-header { + padding: .75rem 1.25rem; + background-color: rgba(0, 0, 0, .03) +} + +.card-title { + margin-bottom: .75rem +} + +.card-header, +.card-subtitle, +.card-text:last-child { + margin-bottom: 0 +} + +.card-subtitle { + margin-top: -.375rem +} + +.card-link:hover { + text-decoration: none +} + +.card-link+.card-link { + margin-left: 1.25rem +} + +.card-header-pills, +.card-header-tabs { + margin-right: -.625rem; + margin-left: -.625rem +} + +.card-header { + border-bottom: 1px solid rgba(0, 0, 0, .125) +} + +.card-header:first-child { + border-radius: -webkit-calc(.25rem - 1px) -webkit-calc(.25rem - 1px) 0 0; + border-radius: calc(.25rem - 1px) calc(.25rem - 1px) 0 0 +} + +.card-header+.list-group .list-group-item:first-child { + border-top: 0 +} + +.card-footer { + border-top: 1px solid rgba(0, 0, 0, .125) +} + +.card-footer:last-child { + border-radius: 0 0 -webkit-calc(.25rem - 1px) -webkit-calc(.25rem - 1px); + border-radius: 0 0 calc(.25rem - 1px) calc(.25rem - 1px) +} + +.card-header-tabs { + margin-bottom: -.75rem; + border-bottom: 0 +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1.25rem +} + +.alert, +.btn .badge, +.page-link { + position: relative +} + +.card-img { + width: 100%; + border-radius: -webkit-calc(.25rem - 1px); + border-radius: calc(.25rem - 1px) +} + +.card-img-top { + width: 100%; + border-top-left-radius: -webkit-calc(.25rem - 1px); + border-top-left-radius: calc(.25rem - 1px); + border-top-right-radius: -webkit-calc(.25rem - 1px); + border-top-right-radius: calc(.25rem - 1px) +} + +.card-img-bottom { + width: 100%; + border-bottom-right-radius: -webkit-calc(.25rem - 1px); + border-bottom-right-radius: calc(.25rem - 1px); + border-bottom-left-radius: -webkit-calc(.25rem - 1px); + border-bottom-left-radius: calc(.25rem - 1px) +} + +.card-deck { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-direction: column; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + flex-direction: column +} + +.card-deck .card { + margin-bottom: 15px +} + +@media (min-width: 576px) { + .card-deck, + .card-deck .card { + -webkit-box-direction: normal + } + .card-deck { + -ms-flex-flow: row wrap; + -webkit-box-orient: horizontal; + -webkit-flex-flow: row wrap; + flex-flow: row wrap; + margin-right: -15px; + margin-left: -15px + } + .card-deck .card { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex: 1 0 0%; + -webkit-box-flex: 1; + -webkit-flex: 1 0 0%; + flex: 1 0 0%; + -ms-flex-direction: column; + -webkit-box-orient: vertical; + -webkit-flex-direction: column; + flex-direction: column; + margin-right: 15px; + margin-bottom: 0; + margin-left: 15px + } +} + +.card-group, +.list-group { + -ms-flex-direction: column +} + +.card-group { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + flex-direction: column +} + +.card-group .card { + margin-bottom: 15px +} + +@media (min-width: 576px) { + .card-group { + -ms-flex-flow: row wrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-flow: row wrap; + flex-flow: row wrap + } + .card-group .card { + -ms-flex: 1 0 0%; + -webkit-box-flex: 1; + -webkit-flex: 1 0 0%; + flex: 1 0 0%; + margin-bottom: 0 + } + .card-group .card+.card { + margin-left: 0; + border-left: 0 + } + .card-group .card:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0 + } + .card-group .card:first-child .card-img-top { + border-top-right-radius: 0 + } + .card-group .card:first-child .card-img-bottom { + border-bottom-right-radius: 0 + } + .card-group .card:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0 + } + .card-group .card:last-child .card-img-top { + border-top-left-radius: 0 + } + .card-group .card:last-child .card-img-bottom { + border-bottom-left-radius: 0 + } + .card-group .card:only-child { + border-radius: .25rem + } + .card-group .card:only-child .card-img-top { + border-top-left-radius: .25rem; + border-top-right-radius: .25rem + } + .card-group .card:only-child .card-img-bottom { + border-bottom-right-radius: .25rem; + border-bottom-left-radius: .25rem + } + .card-group .card:not(:first-child):not(:last-child):not(:only-child), + .card-group .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom, + .card-group .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top { + border-radius: 0 + } + .card-columns { + -webkit-column-count: 3; + -moz-column-count: 3; + column-count: 3; + -webkit-column-gap: 1.25rem; + -moz-column-gap: 1.25rem; + column-gap: 1.25rem + } + .card-columns .card { + display: inline-block; + width: 100% + } +} + +.list-group, +.modal-content { + -webkit-box-orient: vertical; + -webkit-box-direction: normal +} + +.breadcrumb, +.pagination { + border-radius: .25rem; + list-style: none +} + +.card-columns .card { + margin-bottom: .75rem +} + +.breadcrumb { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + padding: .75rem 1rem; + margin-bottom: 1rem; + background-color: #e9ecef +} + +.breadcrumb-item+.breadcrumb-item::before { + display: inline-block; + padding-right: .5rem; + padding-left: .5rem; + color: #868e96; + content: "/" +} + +.breadcrumb-item+.breadcrumb-item:hover::before { + text-decoration: none +} + +.breadcrumb-item.active { + color: #868e96 +} + +.pagination { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + padding-left: 0 +} + +.page-item:first-child .page-link { + margin-left: 0; + border-top-left-radius: .25rem; + border-bottom-left-radius: .25rem +} + +.page-item:last-child .page-link { + border-top-right-radius: .25rem; + border-bottom-right-radius: .25rem +} + +.page-item.active .page-link { + z-index: 2; + color: #fff; + background-color: #007bff; + border-color: #007bff +} + +.page-item.disabled .page-link { + color: #868e96; + pointer-events: none; + background-color: #fff; + border-color: #ddd +} + +.page-link { + display: block; + padding: .5rem .75rem; + margin-left: -1px; + line-height: 1.25; + color: #007bff; + background-color: #fff; + border: 1px solid #ddd +} + +.page-link:focus, +.page-link:hover { + color: #0056b3; + text-decoration: none; + background-color: #e9ecef; + border-color: #ddd +} + +.pagination-lg .page-link { + padding: .75rem 1.5rem; + font-size: 1.25rem; + line-height: 1.5 +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: .3rem; + border-bottom-left-radius: .3rem +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: .3rem; + border-bottom-right-radius: .3rem +} + +.pagination-sm .page-link { + padding: .25rem .5rem; + font-size: .875rem; + line-height: 1.5 +} + +.badge, +.close { + font-weight: 700; + line-height: 1 +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: .2rem; + border-bottom-left-radius: .2rem +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: .2rem; + border-bottom-right-radius: .2rem +} + +.badge { + display: inline-block; + padding: .25em .4em; + font-size: 75%; + text-align: center; + white-space: nowrap; + vertical-align: baseline +} + +.badge:empty { + display: none +} + +.media, +.progress-bar { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex +} + +.btn .badge { + top: -1px +} + +.badge-primary { + color: #fff +} + +.badge-primary[href]:focus, +.badge-primary[href]:hover { + color: #fff; + text-decoration: none; + background-color: #0062cc +} + +.badge-secondary { + color: #fff +} + +.badge-secondary[href]:focus, +.badge-secondary[href]:hover { + color: #fff; + text-decoration: none; + background-color: #6c757d +} + +.badge-success { + color: #fff +} + +.badge-success[href]:focus, +.badge-success[href]:hover { + color: #fff; + text-decoration: none; + background-color: #1e7e34 +} + +.badge-info { + color: #fff +} + +.badge-info[href]:focus, +.badge-info[href]:hover { + color: #fff; + text-decoration: none; + background-color: #117a8b +} + +.badge-warning[href]:focus, +.badge-warning[href]:hover { + color: #111; + text-decoration: none; + background-color: #d39e00 +} + +.badge-danger { + color: #fff +} + +.badge-danger[href]:focus, +.badge-danger[href]:hover { + color: #fff; + text-decoration: none; + background-color: #bd2130 +} + +.badge-light { + color: #111; + background-color: #f8f9fa +} + +.badge-light[href]:focus, +.badge-light[href]:hover { + color: #111; + text-decoration: none; + background-color: #dae0e5 +} + +.badge-dark { + color: #fff; + background-color: #343a40 +} + +.badge-dark[href]:focus, +.badge-dark[href]:hover { + color: #fff; + text-decoration: none; + background-color: #1d2124 +} + +.jumbotron { + margin-bottom: 2rem +} + +@media (min-width: 576px) { + .jumbotron { + padding: 4rem 2rem + } +} + +.jumbotron-fluid { + padding-right: 0; + padding-left: 0; + border-radius: 0 +} + +.alert { + padding: .75rem 1.25rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: .25rem +} + +.alert-heading { + color: inherit +} + +.alert-link { + font-weight: 700 +} + +.alert-dismissible .close { + position: absolute; + top: 0; + right: 0; + padding: .75rem 1.25rem; + color: inherit +} + +.alert-primary { + color: #004085; + background-color: #cce5ff; + border-color: #b8daff +} + +.alert-primary hr { + border-top-color: #9fcdff +} + +.alert-primary .alert-link { + color: #002752 +} + +.alert-secondary { + color: #464a4e; + background-color: #e7e8ea; + border-color: #dddfe2 +} + +.alert-secondary hr { + border-top-color: #cfd2d6 +} + +.alert-secondary .alert-link { + color: #2e3133 +} + +.alert-success { + color: #155724; + background-color: #d4edda; + border-color: #c3e6cb +} + +.alert-success hr { + border-top-color: #b1dfbb +} + +.alert-success .alert-link { + color: #0b2e13 +} + +.alert-info { + color: #0c5460; + background-color: #d1ecf1; + border-color: #bee5eb +} + +.alert-info hr { + border-top-color: #abdde5 +} + +.alert-info .alert-link { + color: #062c33 +} + +.alert-warning { + color: #856404; + background-color: #fff3cd; + border-color: #ffeeba +} + +.alert-warning hr { + border-top-color: #ffe8a1 +} + +.alert-warning .alert-link { + color: #533f03 +} + +.alert-danger { + color: #721c24; + background-color: #f8d7da; + border-color: #f5c6cb +} + +.alert-danger hr { + border-top-color: #f1b0b7 +} + +.alert-danger .alert-link { + color: #491217 +} + +.alert-light { + color: #818182; + background-color: #fefefe; + border-color: #fdfdfe +} + +.alert-light hr { + border-top-color: #ececf6 +} + +.alert-light .alert-link { + color: #686868 +} + +.alert-dark { + color: #1b1e21; + background-color: #d6d8d9; + border-color: #c6c8ca +} + +.alert-dark hr { + border-top-color: #b9bbbe +} + +.alert-dark .alert-link { + color: #040505 +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 1rem 0 + } + to { + background-position: 0 0 + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 1rem 0 + } + to { + background-position: 0 0 + } +} + +.progress { + font-size: .75rem; + border-radius: .25rem +} + +.progress-bar { + display: flex; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + color: #fff; + background-color: #007bff +} + +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-size: 1rem 1rem +} + +.progress-bar-animated { + -webkit-animation: progress-bar-stripes 1s linear infinite; + animation: progress-bar-stripes 1s linear infinite +} + +.media { + display: flex; + -ms-flex-align: start; + -webkit-box-align: start; + -webkit-align-items: flex-start; + align-items: flex-start +} + +.media-body { + -ms-flex: 1; + -webkit-box-flex: 1; + -webkit-flex: 1; + flex: 1 +} + +.list-group { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -webkit-flex-direction: column; + flex-direction: column; + padding-left: 0; + margin-bottom: 0 +} + +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit +} + +.list-group-item-action:focus, +.list-group-item-action:hover { + color: #495057; + text-decoration: none; + background-color: #f8f9fa +} + +.list-group-item-action:active { + color: #212529; + background-color: #e9ecef +} + +.list-group-item { + position: relative; + display: block; + padding: .75rem 1.25rem; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, .125) +} + +.list-group-item:first-child { + border-top-left-radius: .25rem; + border-top-right-radius: .25rem +} + +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: .25rem; + border-bottom-left-radius: .25rem +} + +.list-group-item:focus, +.list-group-item:hover { + text-decoration: none +} + +.list-group-item.disabled, +.list-group-item:disabled { + color: #868e96; + background-color: #fff +} + +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #007bff; + border-color: #007bff +} + +.list-group-flush .list-group-item { + border-right: 0; + border-left: 0; + border-radius: 0 +} + +.list-group-flush:first-child .list-group-item:first-child { + border-top: 0 +} + +.list-group-flush:last-child .list-group-item:last-child { + border-bottom: 0 +} + +.list-group-item-primary { + color: #004085; + background-color: #b8daff +} + +a.list-group-item-primary, +button.list-group-item-primary { + color: #004085 +} + +a.list-group-item-primary:focus, +a.list-group-item-primary:hover, +button.list-group-item-primary:focus, +button.list-group-item-primary:hover { + color: #004085; + background-color: #9fcdff +} + +a.list-group-item-primary.active, +button.list-group-item-primary.active { + color: #fff; + background-color: #004085; + border-color: #004085 +} + +.list-group-item-secondary { + color: #464a4e; + background-color: #dddfe2 +} + +a.list-group-item-secondary, +button.list-group-item-secondary { + color: #464a4e +} + +a.list-group-item-secondary:focus, +a.list-group-item-secondary:hover, +button.list-group-item-secondary:focus, +button.list-group-item-secondary:hover { + color: #464a4e; + background-color: #cfd2d6 +} + +a.list-group-item-secondary.active, +button.list-group-item-secondary.active { + color: #fff; + background-color: #464a4e; + border-color: #464a4e +} + +.list-group-item-success { + color: #155724; + background-color: #c3e6cb +} + +a.list-group-item-success, +button.list-group-item-success { + color: #155724 +} + +a.list-group-item-success:focus, +a.list-group-item-success:hover, +button.list-group-item-success:focus, +button.list-group-item-success:hover { + color: #155724; + background-color: #b1dfbb +} + +a.list-group-item-success.active, +button.list-group-item-success.active { + color: #fff; + background-color: #155724; + border-color: #155724 +} + +.list-group-item-info { + color: #0c5460; + background-color: #bee5eb +} + +a.list-group-item-info, +button.list-group-item-info { + color: #0c5460 +} + +a.list-group-item-info:focus, +a.list-group-item-info:hover, +button.list-group-item-info:focus, +button.list-group-item-info:hover { + color: #0c5460; + background-color: #abdde5 +} + +a.list-group-item-info.active, +button.list-group-item-info.active { + color: #fff; + background-color: #0c5460; + border-color: #0c5460 +} + +.list-group-item-warning { + color: #856404; + background-color: #ffeeba +} + +a.list-group-item-warning, +button.list-group-item-warning { + color: #856404 +} + +a.list-group-item-warning:focus, +a.list-group-item-warning:hover, +button.list-group-item-warning:focus, +button.list-group-item-warning:hover { + color: #856404; + background-color: #ffe8a1 +} + +a.list-group-item-warning.active, +button.list-group-item-warning.active { + color: #fff; + background-color: #856404; + border-color: #856404 +} + +.list-group-item-danger { + color: #721c24; + background-color: #f5c6cb +} + +a.list-group-item-danger, +button.list-group-item-danger { + color: #721c24 +} + +a.list-group-item-danger:focus, +a.list-group-item-danger:hover, +button.list-group-item-danger:focus, +button.list-group-item-danger:hover { + color: #721c24; + background-color: #f1b0b7 +} + +a.list-group-item-danger.active, +button.list-group-item-danger.active { + color: #fff; + background-color: #721c24; + border-color: #721c24 +} + +.list-group-item-light { + color: #818182; + background-color: #fdfdfe +} + +a.list-group-item-light, +button.list-group-item-light { + color: #818182 +} + +a.list-group-item-light:focus, +a.list-group-item-light:hover, +button.list-group-item-light:focus, +button.list-group-item-light:hover { + color: #818182; + background-color: #ececf6 +} + +a.list-group-item-light.active, +button.list-group-item-light.active { + color: #fff; + background-color: #818182; + border-color: #818182 +} + +.list-group-item-dark { + color: #1b1e21; + background-color: #c6c8ca +} + +a.list-group-item-dark, +button.list-group-item-dark { + color: #1b1e21 +} + +a.list-group-item-dark:focus, +a.list-group-item-dark:hover, +button.list-group-item-dark:focus, +button.list-group-item-dark:hover { + color: #1b1e21; + background-color: #b9bbbe +} + +a.list-group-item-dark.active, +button.list-group-item-dark.active { + color: #fff; + background-color: #1b1e21; + border-color: #1b1e21 +} + +.close { + float: right; + font-size: 1.5rem; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: .5 +} + +.popover, +.tooltip { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-style: normal; + font-weight: 400; + text-transform: none; + letter-spacing: normal; + white-space: normal; + line-break: auto; + font-size: .875rem; + word-wrap: break-word; + text-decoration: none; + word-spacing: normal; + word-break: normal +} + +.modal-title, +.popover, +.tooltip { + line-height: 1.5 +} + +.popover, +.text-hide, +.tooltip { + text-shadow: none +} + +.close:focus, +.close:hover { + color: #000; + text-decoration: none; + opacity: .75 +} + +button.close { + padding: 0; + background: 0 0; + border: 0 +} + +.modal-content, +.popover { + background-clip: padding-box +} + +.modal { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1050; + display: none; + outline: 0 +} + +.modal-content, +.modal-header { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex +} + +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + transition: transform .3s ease-out; + transition: transform .3s ease-out, -webkit-transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + transform: translate(0, -25%) +} + +.modal.show .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0) +} + +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto +} + +.modal-dialog { + position: relative; + width: auto; + margin: 10px; + pointer-events: none +} + +.modal-content { + position: relative; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + pointer-events: auto; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: .3rem; + outline: 0 +} + +.flex-column, +.flex-row { + -webkit-box-direction: normal!important +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1040; + background-color: #000 +} + +.modal-backdrop.fade { + opacity: 0 +} + +.modal-backdrop.show { + opacity: .5 +} + +.modal-header { + display: flex; + -ms-flex-align: start; + -webkit-box-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + -ms-flex-pack: justify; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + padding: 15px; + border-bottom: 1px solid #e9ecef; + border-top-left-radius: .3rem; + border-top-right-radius: .3rem +} + +.modal-header .close { + padding: 15px; + margin: -15px -15px -15px auto +} + +.modal-title { + margin-bottom: 0 +} + +.modal-body { + position: relative; + -ms-flex: 1 1 auto; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + padding: 15px +} + +.modal-footer { + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: end; + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + justify-content: flex-end; + padding: 15px; + border-top: 1px solid #e9ecef +} + +.popover, +.popover .arrow, +.popover .arrow::after, +.popover .arrow::before, +.tooltip, +.tooltip .arrow { + position: absolute; + display: block +} + +.modal-footer>:not(:first-child) { + margin-left: .25rem +} + +.modal-footer>:not(:last-child) { + margin-right: .25rem +} + +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll +} + +.popover.bs-popover-auto[x-placement^=bottom] .arrow, +.popover.bs-popover-bottom .arrow, +.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow, +.tooltip.bs-tooltip-bottom .arrow { + top: 0 +} + +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 30px auto + } + .modal-sm { + max-width: 300px + } +} + +@media (min-width: 992px) { + .modal-lg { + max-width: 800px + } +} + +.tooltip { + z-index: 1070; + margin: 0; + text-align: left; + text-align: start; + opacity: 0 +} + +.tooltip.show { + opacity: .9 +} + +.tooltip .arrow { + width: 5px; + height: 5px +} + +.tooltip .arrow::before { + position: absolute; + border-color: transparent; + border-style: solid +} + +.tooltip.bs-tooltip-auto[x-placement^=top], +.tooltip.bs-tooltip-top { + padding: 5px 0 +} + +.tooltip.bs-tooltip-auto[x-placement^=top] .arrow::before, +.tooltip.bs-tooltip-top .arrow::before { + margin-left: -3px; + content: ""; + border-width: 5px 5px 0; + border-top-color: #000 +} + +.tooltip.bs-tooltip-auto[x-placement^=right], +.tooltip.bs-tooltip-right { + padding: 0 5px +} + +.tooltip.bs-tooltip-auto[x-placement^=right] .arrow, +.tooltip.bs-tooltip-right .arrow { + left: 0 +} + +.tooltip.bs-tooltip-auto[x-placement^=right] .arrow::before, +.tooltip.bs-tooltip-right .arrow::before { + margin-top: -3px; + content: ""; + border-width: 5px 5px 5px 0; + border-right-color: #000 +} + +.tooltip.bs-tooltip-auto[x-placement^=bottom], +.tooltip.bs-tooltip-bottom { + padding: 5px 0 +} + +.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::before, +.tooltip.bs-tooltip-bottom .arrow::before { + margin-left: -3px; + content: ""; + border-width: 0 5px 5px; + border-bottom-color: #000 +} + +.tooltip.bs-tooltip-auto[x-placement^=left], +.tooltip.bs-tooltip-left { + padding: 0 5px +} + +.tooltip.bs-tooltip-auto[x-placement^=left] .arrow, +.tooltip.bs-tooltip-left .arrow { + right: 0 +} + +.tooltip.bs-tooltip-auto[x-placement^=left] .arrow::before, +.tooltip.bs-tooltip-left .arrow::before { + right: 0; + margin-top: -3px; + content: ""; + border-width: 5px 0 5px 5px; + border-left-color: #000 +} + +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: .25rem +} + +.popover { + top: 0; + left: 0; + z-index: 1060; + max-width: 276px; + text-align: left; + text-align: start; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: .3rem +} + +.popover .arrow { + width: .8rem; + height: .4rem +} + +.popover .arrow::after, +.popover .arrow::before { + border-color: transparent; + border-style: solid; + content: ""; + border-width: .8rem +} + +.popover.bs-popover-auto[x-placement^=top], +.popover.bs-popover-top { + margin-bottom: .8rem +} + +.popover.bs-popover-auto[x-placement^=top] .arrow::after, +.popover.bs-popover-auto[x-placement^=top] .arrow::before, +.popover.bs-popover-top .arrow::after, +.popover.bs-popover-top .arrow::before { + border-bottom-width: 0 +} + +.popover.bs-popover-auto[x-placement^=top] .arrow::before, +.popover.bs-popover-top .arrow::before { + bottom: -.8rem; + margin-left: -.8rem; + border-top-color: rgba(0, 0, 0, .25) +} + +.popover.bs-popover-auto[x-placement^=top] .arrow::after, +.popover.bs-popover-top .arrow::after { + bottom: -webkit-calc((.8rem - 1px) * -1); + bottom: calc((.8rem - 1px) * -1); + margin-left: -.8rem; + border-top-color: #fff +} + +.popover.bs-popover-auto[x-placement^=right], +.popover.bs-popover-right { + margin-left: .8rem +} + +.popover.bs-popover-auto[x-placement^=right] .arrow, +.popover.bs-popover-right .arrow { + left: 0 +} + +.popover.bs-popover-auto[x-placement^=right] .arrow::after, +.popover.bs-popover-auto[x-placement^=right] .arrow::before, +.popover.bs-popover-right .arrow::after, +.popover.bs-popover-right .arrow::before { + margin-top: -.8rem; + border-left-width: 0 +} + +.popover.bs-popover-auto[x-placement^=right] .arrow::before, +.popover.bs-popover-right .arrow::before { + left: -.8rem; + border-right-color: rgba(0, 0, 0, .25) +} + +.popover.bs-popover-auto[x-placement^=right] .arrow::after, +.popover.bs-popover-right .arrow::after { + left: -webkit-calc((.8rem - 1px) * -1); + left: calc((.8rem - 1px) * -1); + border-right-color: #fff +} + +.popover.bs-popover-auto[x-placement^=bottom], +.popover.bs-popover-bottom { + margin-top: .8rem +} + +.popover.bs-popover-auto[x-placement^=bottom] .arrow::after, +.popover.bs-popover-auto[x-placement^=bottom] .arrow::before, +.popover.bs-popover-bottom .arrow::after, +.popover.bs-popover-bottom .arrow::before { + margin-left: -.8rem; + border-top-width: 0 +} + +.popover.bs-popover-auto[x-placement^=bottom] .arrow::before, +.popover.bs-popover-bottom .arrow::before { + top: -.8rem; + border-bottom-color: rgba(0, 0, 0, .25) +} + +.popover.bs-popover-auto[x-placement^=bottom] .arrow::after, +.popover.bs-popover-bottom .arrow::after { + top: -webkit-calc((.8rem - 1px) * -1); + top: calc((.8rem - 1px) * -1); + border-bottom-color: #fff +} + +.popover.bs-popover-auto[x-placement^=bottom] .popover-header::before, +.popover.bs-popover-bottom .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 20px; + margin-left: -10px; + content: ""; + border-bottom: 1px solid #f7f7f7 +} + +.carousel, +.carousel-inner, +.carousel-item { + position: relative +} + +.popover.bs-popover-auto[x-placement^=left], +.popover.bs-popover-left { + margin-right: .8rem +} + +.popover.bs-popover-auto[x-placement^=left] .arrow, +.popover.bs-popover-left .arrow { + right: 0 +} + +.popover.bs-popover-auto[x-placement^=left] .arrow::after, +.popover.bs-popover-auto[x-placement^=left] .arrow::before, +.popover.bs-popover-left .arrow::after, +.popover.bs-popover-left .arrow::before { + margin-top: -.8rem; + border-right-width: 0 +} + +.popover.bs-popover-auto[x-placement^=left] .arrow::before, +.popover.bs-popover-left .arrow::before { + right: -.8rem; + border-left-color: rgba(0, 0, 0, .25) +} + +.popover.bs-popover-auto[x-placement^=left] .arrow::after, +.popover.bs-popover-left .arrow::after { + right: -webkit-calc((.8rem - 1px) * -1); + right: calc((.8rem - 1px) * -1); + border-left-color: #fff +} + +.popover-header { + padding: .5rem .75rem; + margin-bottom: 0; + font-size: 1rem; + color: inherit; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-top-left-radius: -webkit-calc(.3rem - 1px); + border-top-left-radius: calc(.3rem - 1px); + border-top-right-radius: -webkit-calc(.3rem - 1px); + border-top-right-radius: calc(.3rem - 1px) +} + +.popover-header:empty { + display: none +} + +.popover-body { + padding: .5rem .75rem; + color: #212529 +} + +.carousel-inner { + width: 100%; + overflow: hidden +} + +.carousel-item { + display: none; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + width: 100%; + -webkit-transition: -webkit-transform .6s ease; + transition: transform .6s ease; + transition: transform .6s ease, -webkit-transform .6s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px +} + +.carousel-item-next, +.carousel-item-prev, +.carousel-item.active { + display: block +} + +.carousel-item-next, +.carousel-item-prev { + position: absolute; + top: 0 +} + +.carousel-item-next.carousel-item-left, +.carousel-item-prev.carousel-item-right { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0) +} + +@supports (transform-style: preserve-3d) { + .carousel-item-next.carousel-item-left, + .carousel-item-prev.carousel-item-right { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +.active.carousel-item-right, +.carousel-item-next { + -webkit-transform: translateX(100%); + -ms-transform: translateX(100%); + transform: translateX(100%) +} + +@supports (transform-style: preserve-3d) { + .active.carousel-item-right, + .carousel-item-next { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } +} + +.active.carousel-item-left, +.carousel-item-prev { + -webkit-transform: translateX(-100%); + -ms-transform: translateX(-100%); + transform: translateX(-100%) +} + +@supports (transform-style: preserve-3d) { + .active.carousel-item-left, + .carousel-item-prev { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } +} + +.carousel-control-next, +.carousel-control-prev { + position: absolute; + top: 0; + bottom: 0; + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-align: center; + -webkit-box-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + width: 15%; + color: #fff; + text-align: center; + opacity: .5 +} + +.carousel-control-next:focus, +.carousel-control-next:hover, +.carousel-control-prev:focus, +.carousel-control-prev:hover { + color: #fff; + text-decoration: none; + outline: 0; + opacity: .9 +} + +.carousel-control-prev { + left: 0 +} + +.carousel-control-next { + right: 0 +} + +.carousel-control-next-icon, +.carousel-control-prev-icon { + display: inline-block; + width: 20px; + height: 20px; + background: center center no-repeat; + background-size: 100% 100% +} + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E") +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E") +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 10px; + left: 0; + z-index: 15; + display: -ms-flexbox; + display: -webkit-box; + display: -webkit-flex; + display: flex; + -ms-flex-pack: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + justify-content: center; + padding-left: 0; + margin-right: 15%; + margin-left: 15%; + list-style: none +} + +.carousel-indicators li { + position: relative; + -ms-flex: 0 1 auto; + -webkit-box-flex: 0; + -webkit-flex: 0 1 auto; + flex: 0 1 auto; + width: 30px; + height: 3px; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + background-color: rgba(255, 255, 255, .5) +} + +.carousel-indicators li::after, +.carousel-indicators li::before { + left: 0; + display: inline-block; + height: 10px; + position: absolute; + content: ""; + width: 100% +} + +.carousel-indicators li::before { + top: -10px +} + +.carousel-indicators li::after { + bottom: -10px +} + +.carousel-indicators .active { + background-color: #fff +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center +} + +.align-baseline { + vertical-align: baseline!important +} + +.align-top { + vertical-align: top!important +} + +.align-middle { + vertical-align: middle!important +} + +.align-bottom { + vertical-align: bottom!important +} + +.align-text-bottom { + vertical-align: text-bottom!important +} + +.align-text-top { + vertical-align: text-top!important +} + +.btn .fa, +.btn-floating, +.picker .picker__box, +.picker__date-display .clockpicker-display, +.product-table td, +.switch label .lever, +.waves-input-wrapper { + vertical-align: middle +} + +a.bg-primary:focus, +a.bg-primary:hover { + background-color: #0062cc!important +} + +a.bg-secondary:focus, +a.bg-secondary:hover { + background-color: #6c757d!important +} + +a.bg-success:focus, +a.bg-success:hover { + background-color: #1e7e34!important +} + +a.bg-info:focus, +a.bg-info:hover { + background-color: #117a8b!important +} + +a.bg-warning:focus, +a.bg-warning:hover { + background-color: #d39e00!important +} + +a.bg-danger:focus, +a.bg-danger:hover { + background-color: #bd2130!important +} + +.bg-light { + background-color: #f8f9fa!important +} + +a.bg-light:focus, +a.bg-light:hover { + background-color: #dae0e5!important +} + +.bg-dark { + background-color: #343a40!important +} + +a.bg-dark:focus, +a.bg-dark:hover { + background-color: #1d2124!important +} + +.bg-transparent { + background-color: transparent!important +} + +.border { + border: 1px solid #e9ecef!important +} + +.border-0 { + border: 0!important +} + +.rounded-right, +.rounded-top { + border-top-right-radius: .25rem!important +} + +.rounded-bottom, +.rounded-right { + border-bottom-right-radius: .25rem!important +} + +.rounded-left, +.rounded-top { + border-top-left-radius: .25rem!important +} + +.rounded-bottom, +.rounded-left { + border-bottom-left-radius: .25rem!important +} + +.border-top-0 { + border-top: 0!important +} + +.border-right-0 { + border-right: 0!important +} + +.border-bottom-0 { + border-bottom: 0!important +} + +.border-left-0 { + border-left: 0!important +} + +.border-primary { + border-color: #007bff!important +} + +.border-secondary { + border-color: #868e96!important +} + +.border-success { + border-color: #28a745!important +} + +.border-info { + border-color: #17a2b8!important +} + +.border-warning { + border-color: #ffc107!important +} + +.border-danger { + border-color: #dc3545!important +} + +.border-light { + border-color: #f8f9fa!important +} + +.border-dark { + border-color: #343a40!important +} + +.border-white { + border-color: #fff!important +} + +.rounded { + border-radius: .25rem!important +} + +.rounded-circle { + border-radius: 50%!important +} + +.rounded-0 { + border-radius: 0!important +} + +.clearfix::after { + display: block; + clear: both; + content: "" +} + +.d-none { + display: none!important +} + +.d-inline { + display: inline!important +} + +.d-inline-block { + display: inline-block!important +} + +.d-block { + display: block!important +} + +.d-table { + display: table!important +} + +.d-table-row { + display: table-row!important +} + +.d-table-cell { + display: table-cell!important +} + +.d-flex { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important +} + +.d-inline-flex { + display: -ms-inline-flexbox!important; + display: -webkit-inline-box!important; + display: -webkit-inline-flex!important; + display: inline-flex!important +} + +@media (min-width: 576px) { + .d-sm-none { + display: none!important + } + .d-sm-inline { + display: inline!important + } + .d-sm-inline-block { + display: inline-block!important + } + .d-sm-block { + display: block!important + } + .d-sm-table { + display: table!important + } + .d-sm-table-row { + display: table-row!important + } + .d-sm-table-cell { + display: table-cell!important + } + .d-sm-flex { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important + } + .d-sm-inline-flex { + display: -ms-inline-flexbox!important; + display: -webkit-inline-box!important; + display: -webkit-inline-flex!important; + display: inline-flex!important + } +} + +@media (min-width: 768px) { + .d-md-none { + display: none!important + } + .d-md-inline { + display: inline!important + } + .d-md-inline-block { + display: inline-block!important + } + .d-md-block { + display: block!important + } + .d-md-table { + display: table!important + } + .d-md-table-row { + display: table-row!important + } + .d-md-table-cell { + display: table-cell!important + } + .d-md-flex { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important + } + .d-md-inline-flex { + display: -ms-inline-flexbox!important; + display: -webkit-inline-box!important; + display: -webkit-inline-flex!important; + display: inline-flex!important + } +} + +@media (min-width: 992px) { + .d-lg-none { + display: none!important + } + .d-lg-inline { + display: inline!important + } + .d-lg-inline-block { + display: inline-block!important + } + .d-lg-block { + display: block!important + } + .d-lg-table { + display: table!important + } + .d-lg-table-row { + display: table-row!important + } + .d-lg-table-cell { + display: table-cell!important + } + .d-lg-flex { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important + } + .d-lg-inline-flex { + display: -ms-inline-flexbox!important; + display: -webkit-inline-box!important; + display: -webkit-inline-flex!important; + display: inline-flex!important + } +} + +@media (min-width: 1200px) { + .d-xl-none { + display: none!important + } + .d-xl-inline { + display: inline!important + } + .d-xl-inline-block { + display: inline-block!important + } + .d-xl-block { + display: block!important + } + .d-xl-table { + display: table!important + } + .d-xl-table-row { + display: table-row!important + } + .d-xl-table-cell { + display: table-cell!important + } + .d-xl-flex { + display: -ms-flexbox!important; + display: -webkit-box!important; + display: -webkit-flex!important; + display: flex!important + } + .d-xl-inline-flex { + display: -ms-inline-flexbox!important; + display: -webkit-inline-box!important; + display: -webkit-inline-flex!important; + display: inline-flex!important + } +} + +.d-print-block { + display: none!important +} + +@media print { + .d-print-block { + display: block!important + } +} + +.d-print-inline { + display: none!important +} + +@media print { + .d-print-inline { + display: inline!important + } +} + +.d-print-inline-block { + display: none!important +} + +@media print { + .d-print-inline-block { + display: inline-block!important + } + .d-print-none { + display: none!important + } +} + +.embed-responsive { + position: relative; + display: block; + width: 100%; + padding: 0; + overflow: hidden +} + +.embed-responsive::before { + display: block; + content: "" +} + +.embed-responsive .embed-responsive-item, +.embed-responsive embed, +.embed-responsive iframe, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0 +} + +.embed-responsive-21by9::before { + padding-top: 42.857143% +} + +.embed-responsive-16by9::before { + padding-top: 56.25% +} + +.embed-responsive-4by3::before { + padding-top: 75% +} + +.embed-responsive-1by1::before { + padding-top: 100% +} + +.flex-row { + -ms-flex-direction: row!important; + -webkit-box-orient: horizontal!important; + -webkit-flex-direction: row!important; + flex-direction: row!important +} + +.flex-column { + -ms-flex-direction: column!important; + -webkit-box-orient: vertical!important; + -webkit-flex-direction: column!important; + flex-direction: column!important +} + +.flex-column-reverse, +.flex-row-reverse { + -webkit-box-direction: reverse!important +} + +.flex-row-reverse { + -ms-flex-direction: row-reverse!important; + -webkit-box-orient: horizontal!important; + -webkit-flex-direction: row-reverse!important; + flex-direction: row-reverse!important +} + +.flex-column-reverse { + -ms-flex-direction: column-reverse!important; + -webkit-box-orient: vertical!important; + -webkit-flex-direction: column-reverse!important; + flex-direction: column-reverse!important +} + +.flex-wrap { + -ms-flex-wrap: wrap!important; + -webkit-flex-wrap: wrap!important; + flex-wrap: wrap!important +} + +.flex-nowrap { + -ms-flex-wrap: nowrap!important; + -webkit-flex-wrap: nowrap!important; + flex-wrap: nowrap!important +} + +.flex-wrap-reverse { + -ms-flex-wrap: wrap-reverse!important; + -webkit-flex-wrap: wrap-reverse!important; + flex-wrap: wrap-reverse!important +} + +.justify-content-start { + -ms-flex-pack: start!important; + -webkit-box-pack: start!important; + -webkit-justify-content: flex-start!important; + justify-content: flex-start!important +} + +.justify-content-end { + -ms-flex-pack: end!important; + -webkit-box-pack: end!important; + -webkit-justify-content: flex-end!important; + justify-content: flex-end!important +} + +.justify-content-center { + -ms-flex-pack: center!important; + -webkit-box-pack: center!important; + -webkit-justify-content: center!important; + justify-content: center!important +} + +.justify-content-between { + -ms-flex-pack: justify!important; + -webkit-box-pack: justify!important; + -webkit-justify-content: space-between!important; + justify-content: space-between!important +} + +.justify-content-around { + -ms-flex-pack: distribute!important; + -webkit-justify-content: space-around!important; + justify-content: space-around!important +} + +.align-items-start { + -ms-flex-align: start!important; + -webkit-box-align: start!important; + -webkit-align-items: flex-start!important; + align-items: flex-start!important +} + +.align-items-end { + -ms-flex-align: end!important; + -webkit-box-align: end!important; + -webkit-align-items: flex-end!important; + align-items: flex-end!important +} + +.align-items-center { + -ms-flex-align: center!important; + -webkit-box-align: center!important; + -webkit-align-items: center!important; + align-items: center!important +} + +.align-items-baseline { + -ms-flex-align: baseline!important; + -webkit-box-align: baseline!important; + -webkit-align-items: baseline!important; + align-items: baseline!important +} + +.align-items-stretch { + -ms-flex-align: stretch!important; + -webkit-box-align: stretch!important; + -webkit-align-items: stretch!important; + align-items: stretch!important +} + +.align-content-start { + -ms-flex-line-pack: start!important; + -webkit-align-content: flex-start!important; + align-content: flex-start!important +} + +.align-content-end { + -ms-flex-line-pack: end!important; + -webkit-align-content: flex-end!important; + align-content: flex-end!important +} + +.align-content-center { + -ms-flex-line-pack: center!important; + -webkit-align-content: center!important; + align-content: center!important +} + +.align-content-between { + -ms-flex-line-pack: justify!important; + -webkit-align-content: space-between!important; + align-content: space-between!important +} + +.align-content-around { + -ms-flex-line-pack: distribute!important; + -webkit-align-content: space-around!important; + align-content: space-around!important +} + +.align-content-stretch { + -ms-flex-line-pack: stretch!important; + -webkit-align-content: stretch!important; + align-content: stretch!important +} + +.align-self-auto { + -ms-flex-item-align: auto!important; + -webkit-align-self: auto!important; + -ms-grid-row-align: auto!important; + align-self: auto!important +} + +.align-self-start { + -ms-flex-item-align: start!important; + -webkit-align-self: flex-start!important; + align-self: flex-start!important +} + +.align-self-end { + -ms-flex-item-align: end!important; + -webkit-align-self: flex-end!important; + align-self: flex-end!important +} + +.align-self-center { + -ms-flex-item-align: center!important; + -webkit-align-self: center!important; + -ms-grid-row-align: center!important; + align-self: center!important +} + +.align-self-baseline { + -ms-flex-item-align: baseline!important; + -webkit-align-self: baseline!important; + align-self: baseline!important +} + +.align-self-stretch { + -ms-flex-item-align: stretch!important; + -webkit-align-self: stretch!important; + -ms-grid-row-align: stretch!important; + align-self: stretch!important +} + +@media (min-width: 576px) { + .flex-sm-column, + .flex-sm-row { + -webkit-box-direction: normal!important + } + .flex-sm-row { + -ms-flex-direction: row!important; + -webkit-box-orient: horizontal!important; + -webkit-flex-direction: row!important; + flex-direction: row!important + } + .flex-sm-column { + -ms-flex-direction: column!important; + -webkit-box-orient: vertical!important; + -webkit-flex-direction: column!important; + flex-direction: column!important + } + .flex-sm-row-reverse { + -ms-flex-direction: row-reverse!important; + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -webkit-flex-direction: row-reverse!important; + flex-direction: row-reverse!important + } + .flex-sm-column-reverse { + -ms-flex-direction: column-reverse!important; + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -webkit-flex-direction: column-reverse!important; + flex-direction: column-reverse!important + } + .flex-sm-wrap { + -ms-flex-wrap: wrap!important; + -webkit-flex-wrap: wrap!important; + flex-wrap: wrap!important + } + .flex-sm-nowrap { + -ms-flex-wrap: nowrap!important; + -webkit-flex-wrap: nowrap!important; + flex-wrap: nowrap!important + } + .flex-sm-wrap-reverse { + -ms-flex-wrap: wrap-reverse!important; + -webkit-flex-wrap: wrap-reverse!important; + flex-wrap: wrap-reverse!important + } + .justify-content-sm-start { + -ms-flex-pack: start!important; + -webkit-box-pack: start!important; + -webkit-justify-content: flex-start!important; + justify-content: flex-start!important + } + .justify-content-sm-end { + -ms-flex-pack: end!important; + -webkit-box-pack: end!important; + -webkit-justify-content: flex-end!important; + justify-content: flex-end!important + } + .justify-content-sm-center { + -ms-flex-pack: center!important; + -webkit-box-pack: center!important; + -webkit-justify-content: center!important; + justify-content: center!important + } + .justify-content-sm-between { + -ms-flex-pack: justify!important; + -webkit-box-pack: justify!important; + -webkit-justify-content: space-between!important; + justify-content: space-between!important + } + .justify-content-sm-around { + -ms-flex-pack: distribute!important; + -webkit-justify-content: space-around!important; + justify-content: space-around!important + } + .align-items-sm-start { + -ms-flex-align: start!important; + -webkit-box-align: start!important; + -webkit-align-items: flex-start!important; + align-items: flex-start!important + } + .align-items-sm-end { + -ms-flex-align: end!important; + -webkit-box-align: end!important; + -webkit-align-items: flex-end!important; + align-items: flex-end!important + } + .align-items-sm-center { + -ms-flex-align: center!important; + -webkit-box-align: center!important; + -webkit-align-items: center!important; + align-items: center!important + } + .align-items-sm-baseline { + -ms-flex-align: baseline!important; + -webkit-box-align: baseline!important; + -webkit-align-items: baseline!important; + align-items: baseline!important + } + .align-items-sm-stretch { + -ms-flex-align: stretch!important; + -webkit-box-align: stretch!important; + -webkit-align-items: stretch!important; + align-items: stretch!important + } + .align-content-sm-start { + -ms-flex-line-pack: start!important; + -webkit-align-content: flex-start!important; + align-content: flex-start!important + } + .align-content-sm-end { + -ms-flex-line-pack: end!important; + -webkit-align-content: flex-end!important; + align-content: flex-end!important + } + .align-content-sm-center { + -ms-flex-line-pack: center!important; + -webkit-align-content: center!important; + align-content: center!important + } + .align-content-sm-between { + -ms-flex-line-pack: justify!important; + -webkit-align-content: space-between!important; + align-content: space-between!important + } + .align-content-sm-around { + -ms-flex-line-pack: distribute!important; + -webkit-align-content: space-around!important; + align-content: space-around!important + } + .align-content-sm-stretch { + -ms-flex-line-pack: stretch!important; + -webkit-align-content: stretch!important; + align-content: stretch!important + } + .align-self-sm-auto { + -ms-flex-item-align: auto!important; + -webkit-align-self: auto!important; + -ms-grid-row-align: auto!important; + align-self: auto!important + } + .align-self-sm-start { + -ms-flex-item-align: start!important; + -webkit-align-self: flex-start!important; + align-self: flex-start!important + } + .align-self-sm-end { + -ms-flex-item-align: end!important; + -webkit-align-self: flex-end!important; + align-self: flex-end!important + } + .align-self-sm-center { + -ms-flex-item-align: center!important; + -webkit-align-self: center!important; + -ms-grid-row-align: center!important; + align-self: center!important + } + .align-self-sm-baseline { + -ms-flex-item-align: baseline!important; + -webkit-align-self: baseline!important; + align-self: baseline!important + } + .align-self-sm-stretch { + -ms-flex-item-align: stretch!important; + -webkit-align-self: stretch!important; + -ms-grid-row-align: stretch!important; + align-self: stretch!important + } +} + +@media (min-width: 768px) { + .flex-md-column, + .flex-md-row { + -webkit-box-direction: normal!important + } + .flex-md-row { + -ms-flex-direction: row!important; + -webkit-box-orient: horizontal!important; + -webkit-flex-direction: row!important; + flex-direction: row!important + } + .flex-md-column { + -ms-flex-direction: column!important; + -webkit-box-orient: vertical!important; + -webkit-flex-direction: column!important; + flex-direction: column!important + } + .flex-md-row-reverse { + -ms-flex-direction: row-reverse!important; + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -webkit-flex-direction: row-reverse!important; + flex-direction: row-reverse!important + } + .flex-md-column-reverse { + -ms-flex-direction: column-reverse!important; + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -webkit-flex-direction: column-reverse!important; + flex-direction: column-reverse!important + } + .flex-md-wrap { + -ms-flex-wrap: wrap!important; + -webkit-flex-wrap: wrap!important; + flex-wrap: wrap!important + } + .flex-md-nowrap { + -ms-flex-wrap: nowrap!important; + -webkit-flex-wrap: nowrap!important; + flex-wrap: nowrap!important + } + .flex-md-wrap-reverse { + -ms-flex-wrap: wrap-reverse!important; + -webkit-flex-wrap: wrap-reverse!important; + flex-wrap: wrap-reverse!important + } + .justify-content-md-start { + -ms-flex-pack: start!important; + -webkit-box-pack: start!important; + -webkit-justify-content: flex-start!important; + justify-content: flex-start!important + } + .justify-content-md-end { + -ms-flex-pack: end!important; + -webkit-box-pack: end!important; + -webkit-justify-content: flex-end!important; + justify-content: flex-end!important + } + .justify-content-md-center { + -ms-flex-pack: center!important; + -webkit-box-pack: center!important; + -webkit-justify-content: center!important; + justify-content: center!important + } + .justify-content-md-between { + -ms-flex-pack: justify!important; + -webkit-box-pack: justify!important; + -webkit-justify-content: space-between!important; + justify-content: space-between!important + } + .justify-content-md-around { + -ms-flex-pack: distribute!important; + -webkit-justify-content: space-around!important; + justify-content: space-around!important + } + .align-items-md-start { + -ms-flex-align: start!important; + -webkit-box-align: start!important; + -webkit-align-items: flex-start!important; + align-items: flex-start!important + } + .align-items-md-end { + -ms-flex-align: end!important; + -webkit-box-align: end!important; + -webkit-align-items: flex-end!important; + align-items: flex-end!important + } + .align-items-md-center { + -ms-flex-align: center!important; + -webkit-box-align: center!important; + -webkit-align-items: center!important; + align-items: center!important + } + .align-items-md-baseline { + -ms-flex-align: baseline!important; + -webkit-box-align: baseline!important; + -webkit-align-items: baseline!important; + align-items: baseline!important + } + .align-items-md-stretch { + -ms-flex-align: stretch!important; + -webkit-box-align: stretch!important; + -webkit-align-items: stretch!important; + align-items: stretch!important + } + .align-content-md-start { + -ms-flex-line-pack: start!important; + -webkit-align-content: flex-start!important; + align-content: flex-start!important + } + .align-content-md-end { + -ms-flex-line-pack: end!important; + -webkit-align-content: flex-end!important; + align-content: flex-end!important + } + .align-content-md-center { + -ms-flex-line-pack: center!important; + -webkit-align-content: center!important; + align-content: center!important + } + .align-content-md-between { + -ms-flex-line-pack: justify!important; + -webkit-align-content: space-between!important; + align-content: space-between!important + } + .align-content-md-around { + -ms-flex-line-pack: distribute!important; + -webkit-align-content: space-around!important; + align-content: space-around!important + } + .align-content-md-stretch { + -ms-flex-line-pack: stretch!important; + -webkit-align-content: stretch!important; + align-content: stretch!important + } + .align-self-md-auto { + -ms-flex-item-align: auto!important; + -webkit-align-self: auto!important; + -ms-grid-row-align: auto!important; + align-self: auto!important + } + .align-self-md-start { + -ms-flex-item-align: start!important; + -webkit-align-self: flex-start!important; + align-self: flex-start!important + } + .align-self-md-end { + -ms-flex-item-align: end!important; + -webkit-align-self: flex-end!important; + align-self: flex-end!important + } + .align-self-md-center { + -ms-flex-item-align: center!important; + -webkit-align-self: center!important; + -ms-grid-row-align: center!important; + align-self: center!important + } + .align-self-md-baseline { + -ms-flex-item-align: baseline!important; + -webkit-align-self: baseline!important; + align-self: baseline!important + } + .align-self-md-stretch { + -ms-flex-item-align: stretch!important; + -webkit-align-self: stretch!important; + -ms-grid-row-align: stretch!important; + align-self: stretch!important + } +} + +@media (min-width: 992px) { + .flex-lg-column, + .flex-lg-row { + -webkit-box-direction: normal!important + } + .flex-lg-row { + -ms-flex-direction: row!important; + -webkit-box-orient: horizontal!important; + -webkit-flex-direction: row!important; + flex-direction: row!important + } + .flex-lg-column { + -ms-flex-direction: column!important; + -webkit-box-orient: vertical!important; + -webkit-flex-direction: column!important; + flex-direction: column!important + } + .flex-lg-row-reverse { + -ms-flex-direction: row-reverse!important; + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -webkit-flex-direction: row-reverse!important; + flex-direction: row-reverse!important + } + .flex-lg-column-reverse { + -ms-flex-direction: column-reverse!important; + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -webkit-flex-direction: column-reverse!important; + flex-direction: column-reverse!important + } + .flex-lg-wrap { + -ms-flex-wrap: wrap!important; + -webkit-flex-wrap: wrap!important; + flex-wrap: wrap!important + } + .flex-lg-nowrap { + -ms-flex-wrap: nowrap!important; + -webkit-flex-wrap: nowrap!important; + flex-wrap: nowrap!important + } + .flex-lg-wrap-reverse { + -ms-flex-wrap: wrap-reverse!important; + -webkit-flex-wrap: wrap-reverse!important; + flex-wrap: wrap-reverse!important + } + .justify-content-lg-start { + -ms-flex-pack: start!important; + -webkit-box-pack: start!important; + -webkit-justify-content: flex-start!important; + justify-content: flex-start!important + } + .justify-content-lg-end { + -ms-flex-pack: end!important; + -webkit-box-pack: end!important; + -webkit-justify-content: flex-end!important; + justify-content: flex-end!important + } + .justify-content-lg-center { + -ms-flex-pack: center!important; + -webkit-box-pack: center!important; + -webkit-justify-content: center!important; + justify-content: center!important + } + .justify-content-lg-between { + -ms-flex-pack: justify!important; + -webkit-box-pack: justify!important; + -webkit-justify-content: space-between!important; + justify-content: space-between!important + } + .justify-content-lg-around { + -ms-flex-pack: distribute!important; + -webkit-justify-content: space-around!important; + justify-content: space-around!important + } + .align-items-lg-start { + -ms-flex-align: start!important; + -webkit-box-align: start!important; + -webkit-align-items: flex-start!important; + align-items: flex-start!important + } + .align-items-lg-end { + -ms-flex-align: end!important; + -webkit-box-align: end!important; + -webkit-align-items: flex-end!important; + align-items: flex-end!important + } + .align-items-lg-center { + -ms-flex-align: center!important; + -webkit-box-align: center!important; + -webkit-align-items: center!important; + align-items: center!important + } + .align-items-lg-baseline { + -ms-flex-align: baseline!important; + -webkit-box-align: baseline!important; + -webkit-align-items: baseline!important; + align-items: baseline!important + } + .align-items-lg-stretch { + -ms-flex-align: stretch!important; + -webkit-box-align: stretch!important; + -webkit-align-items: stretch!important; + align-items: stretch!important + } + .align-content-lg-start { + -ms-flex-line-pack: start!important; + -webkit-align-content: flex-start!important; + align-content: flex-start!important + } + .align-content-lg-end { + -ms-flex-line-pack: end!important; + -webkit-align-content: flex-end!important; + align-content: flex-end!important + } + .align-content-lg-center { + -ms-flex-line-pack: center!important; + -webkit-align-content: center!important; + align-content: center!important + } + .align-content-lg-between { + -ms-flex-line-pack: justify!important; + -webkit-align-content: space-between!important; + align-content: space-between!important + } + .align-content-lg-around { + -ms-flex-line-pack: distribute!important; + -webkit-align-content: space-around!important; + align-content: space-around!important + } + .align-content-lg-stretch { + -ms-flex-line-pack: stretch!important; + -webkit-align-content: stretch!important; + align-content: stretch!important + } + .align-self-lg-auto { + -ms-flex-item-align: auto!important; + -webkit-align-self: auto!important; + -ms-grid-row-align: auto!important; + align-self: auto!important + } + .align-self-lg-start { + -ms-flex-item-align: start!important; + -webkit-align-self: flex-start!important; + align-self: flex-start!important + } + .align-self-lg-end { + -ms-flex-item-align: end!important; + -webkit-align-self: flex-end!important; + align-self: flex-end!important + } + .align-self-lg-center { + -ms-flex-item-align: center!important; + -webkit-align-self: center!important; + -ms-grid-row-align: center!important; + align-self: center!important + } + .align-self-lg-baseline { + -ms-flex-item-align: baseline!important; + -webkit-align-self: baseline!important; + align-self: baseline!important + } + .align-self-lg-stretch { + -ms-flex-item-align: stretch!important; + -webkit-align-self: stretch!important; + -ms-grid-row-align: stretch!important; + align-self: stretch!important + } +} + +@media (min-width: 1200px) { + .flex-xl-column, + .flex-xl-row { + -webkit-box-direction: normal!important + } + .flex-xl-row { + -ms-flex-direction: row!important; + -webkit-box-orient: horizontal!important; + -webkit-flex-direction: row!important; + flex-direction: row!important + } + .flex-xl-column { + -ms-flex-direction: column!important; + -webkit-box-orient: vertical!important; + -webkit-flex-direction: column!important; + flex-direction: column!important + } + .flex-xl-row-reverse { + -ms-flex-direction: row-reverse!important; + -webkit-box-orient: horizontal!important; + -webkit-box-direction: reverse!important; + -webkit-flex-direction: row-reverse!important; + flex-direction: row-reverse!important + } + .flex-xl-column-reverse { + -ms-flex-direction: column-reverse!important; + -webkit-box-orient: vertical!important; + -webkit-box-direction: reverse!important; + -webkit-flex-direction: column-reverse!important; + flex-direction: column-reverse!important + } + .flex-xl-wrap { + -ms-flex-wrap: wrap!important; + -webkit-flex-wrap: wrap!important; + flex-wrap: wrap!important + } + .flex-xl-nowrap { + -ms-flex-wrap: nowrap!important; + -webkit-flex-wrap: nowrap!important; + flex-wrap: nowrap!important + } + .flex-xl-wrap-reverse { + -ms-flex-wrap: wrap-reverse!important; + -webkit-flex-wrap: wrap-reverse!important; + flex-wrap: wrap-reverse!important + } + .justify-content-xl-start { + -ms-flex-pack: start!important; + -webkit-box-pack: start!important; + -webkit-justify-content: flex-start!important; + justify-content: flex-start!important + } + .justify-content-xl-end { + -ms-flex-pack: end!important; + -webkit-box-pack: end!important; + -webkit-justify-content: flex-end!important; + justify-content: flex-end!important + } + .justify-content-xl-center { + -ms-flex-pack: center!important; + -webkit-box-pack: center!important; + -webkit-justify-content: center!important; + justify-content: center!important + } + .justify-content-xl-between { + -ms-flex-pack: justify!important; + -webkit-box-pack: justify!important; + -webkit-justify-content: space-between!important; + justify-content: space-between!important + } + .justify-content-xl-around { + -ms-flex-pack: distribute!important; + -webkit-justify-content: space-around!important; + justify-content: space-around!important + } + .align-items-xl-start { + -ms-flex-align: start!important; + -webkit-box-align: start!important; + -webkit-align-items: flex-start!important; + align-items: flex-start!important + } + .align-items-xl-end { + -ms-flex-align: end!important; + -webkit-box-align: end!important; + -webkit-align-items: flex-end!important; + align-items: flex-end!important + } + .align-items-xl-center { + -ms-flex-align: center!important; + -webkit-box-align: center!important; + -webkit-align-items: center!important; + align-items: center!important + } + .align-items-xl-baseline { + -ms-flex-align: baseline!important; + -webkit-box-align: baseline!important; + -webkit-align-items: baseline!important; + align-items: baseline!important + } + .align-items-xl-stretch { + -ms-flex-align: stretch!important; + -webkit-box-align: stretch!important; + -webkit-align-items: stretch!important; + align-items: stretch!important + } + .align-content-xl-start { + -ms-flex-line-pack: start!important; + -webkit-align-content: flex-start!important; + align-content: flex-start!important + } + .align-content-xl-end { + -ms-flex-line-pack: end!important; + -webkit-align-content: flex-end!important; + align-content: flex-end!important + } + .align-content-xl-center { + -ms-flex-line-pack: center!important; + -webkit-align-content: center!important; + align-content: center!important + } + .align-content-xl-between { + -ms-flex-line-pack: justify!important; + -webkit-align-content: space-between!important; + align-content: space-between!important + } + .align-content-xl-around { + -ms-flex-line-pack: distribute!important; + -webkit-align-content: space-around!important; + align-content: space-around!important + } + .align-content-xl-stretch { + -ms-flex-line-pack: stretch!important; + -webkit-align-content: stretch!important; + align-content: stretch!important + } + .align-self-xl-auto { + -ms-flex-item-align: auto!important; + -webkit-align-self: auto!important; + -ms-grid-row-align: auto!important; + align-self: auto!important + } + .align-self-xl-start { + -ms-flex-item-align: start!important; + -webkit-align-self: flex-start!important; + align-self: flex-start!important + } + .align-self-xl-end { + -ms-flex-item-align: end!important; + -webkit-align-self: flex-end!important; + align-self: flex-end!important + } + .align-self-xl-center { + -ms-flex-item-align: center!important; + -webkit-align-self: center!important; + -ms-grid-row-align: center!important; + align-self: center!important + } + .align-self-xl-baseline { + -ms-flex-item-align: baseline!important; + -webkit-align-self: baseline!important; + align-self: baseline!important + } + .align-self-xl-stretch { + -ms-flex-item-align: stretch!important; + -webkit-align-self: stretch!important; + -ms-grid-row-align: stretch!important; + align-self: stretch!important + } +} + +.divider-new, +.navbar .nav-flex-icons, +.navbar.double-nav { + -webkit-box-orient: horizontal; + -webkit-box-direction: normal +} + +.float-left { + float: left!important +} + +.float-right { + float: right!important +} + +.float-none { + float: none!important +} + +.position-static { + position: static!important +} + +.position-relative { + position: relative!important +} + +.position-absolute { + position: absolute!important +} + +.position-fixed { + position: fixed!important +} + +.position-sticky { + position: -webkit-sticky!important; + position: sticky!important +} + +.fixed-bottom, +.fixed-top { + position: fixed; + right: 0; + left: 0; + z-index: 1030 +} + +.fixed-top { + top: 0 +} + +.fixed-bottom { + bottom: 0 +} + +@supports ((position: -webkit-sticky) or (position:sticky)) { + .sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020 + } +} + +.btn .fa, +.card .card-body { + position: relative +} + +.sr-only { + white-space: nowrap; + -webkit-clip-path: inset(50%); + clip-path: inset(50%) +} + +.sr-only-focusable:active, +.sr-only-focusable:focus { + white-space: normal; + -webkit-clip-path: none; + clip-path: none +} + +.w-25 { + width: 25%!important +} + +.w-50 { + width: 50%!important +} + +.w-75 { + width: 75%!important +} + +.w-100 { + width: 100%!important +} + +.h-25 { + height: 25%!important +} + +.h-50 { + height: 50%!important +} + +.h-75 { + height: 75%!important +} + +.h-100 { + height: 100%!important +} + +.mw-100 { + max-width: 100%!important +} + +.mh-100 { + max-height: 100%!important +} + +.mt-0, +.my-0 { + margin-top: 0!important +} + +.mr-0, +.mx-0 { + margin-right: 0!important +} + +.mb-0, +.my-0 { + margin-bottom: 0!important +} + +.ml-0, +.mx-0 { + margin-left: 0!important +} + +.m-1 { + margin: .25rem!important +} + +.mt-1, +.my-1 { + margin-top: .25rem!important +} + +.mr-1, +.mx-1 { + margin-right: .25rem!important +} + +.mb-1, +.my-1 { + margin-bottom: .25rem!important +} + +.ml-1, +.mx-1 { + margin-left: .25rem!important +} + +.mt-2, +.my-2 { + margin-top: .5rem!important +} + +.mr-2, +.mx-2 { + margin-right: .5rem!important +} + +.mb-2, +.my-2 { + margin-bottom: .5rem!important +} + +.ml-2, +.mx-2 { + margin-left: .5rem!important +} + +.mt-3, +.my-3 { + margin-top: 1rem!important +} + +.mr-3, +.mx-3 { + margin-right: 1rem!important +} + +.mb-3, +.my-3 { + margin-bottom: 1rem!important +} + +.ml-3, +.mx-3 { + margin-left: 1rem!important +} + +.mt-4, +.my-4 { + margin-top: 1.5rem!important +} + +.mr-4, +.mx-4 { + margin-right: 1.5rem!important +} + +.mb-4, +.my-4 { + margin-bottom: 1.5rem!important +} + +.ml-4, +.mx-4 { + margin-left: 1.5rem!important +} + +.mt-5, +.my-5 { + margin-top: 3rem!important +} + +.mr-5, +.mx-5 { + margin-right: 3rem!important +} + +.mb-5, +.my-5 { + margin-bottom: 3rem!important +} + +.ml-5, +.mx-5 { + margin-left: 3rem!important +} + +.pt-0, +.py-0 { + padding-top: 0!important +} + +.pr-0, +.px-0 { + padding-right: 0!important +} + +.pb-0, +.py-0 { + padding-bottom: 0!important +} + +.pl-0, +.px-0 { + padding-left: 0!important +} + +.pt-1, +.py-1 { + padding-top: .25rem!important +} + +.pr-1, +.px-1 { + padding-right: .25rem!important +} + +.pb-1, +.py-1 { + padding-bottom: .25rem!important +} + +.pl-1, +.px-1 { + padding-left: .25rem!important +} + +.pt-2, +.py-2 { + padding-top: .5rem!important +} + +.pr-2, +.px-2 { + padding-right: .5rem!important +} + +.pb-2, +.py-2 { + padding-bottom: .5rem!important +} + +.pl-2, +.px-2 { + padding-left: .5rem!important +} + +.pt-3, +.py-3 { + padding-top: 1rem!important +} + +.pr-3, +.px-3 { + padding-right: 1rem!important +} + +.pb-3, +.py-3 { + padding-bottom: 1rem!important +} + +.pl-3, +.px-3 { + padding-left: 1rem!important +} + +.pt-4, +.py-4 { + padding-top: 1.5rem!important +} + +.pr-4, +.px-4 { + padding-right: 1.5rem!important +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem!important +} + +.pl-4, +.px-4 { + padding-left: 1.5rem!important +} + +.pt-5, +.py-5 { + padding-top: 3rem!important +} + +.pr-5, +.px-5 { + padding-right: 3rem!important +} + +.pb-5, +.py-5 { + padding-bottom: 3rem!important +} + +.pl-5, +.px-5 { + padding-left: 3rem!important +} + +.mt-auto, +.my-auto { + margin-top: auto!important +} + +.mr-auto, +.mx-auto { + margin-right: auto!important +} + +.mb-auto, +.my-auto { + margin-bottom: auto!important +} + +.ml-auto, +.mx-auto { + margin-left: auto!important +} + +@media (min-width: 576px) { + .float-sm-left { + float: left!important + } + .float-sm-right { + float: right!important + } + .float-sm-none { + float: none!important + } + .m-sm-0 { + margin: 0!important + } + .mt-sm-0, + .my-sm-0 { + margin-top: 0!important + } + .mr-sm-0, + .mx-sm-0 { + margin-right: 0!important + } + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0!important + } + .ml-sm-0, + .mx-sm-0 { + margin-left: 0!important + } + .m-sm-1 { + margin: .25rem!important + } + .mt-sm-1, + .my-sm-1 { + margin-top: .25rem!important + } + .mr-sm-1, + .mx-sm-1 { + margin-right: .25rem!important + } + .mb-sm-1, + .my-sm-1 { + margin-bottom: .25rem!important + } + .ml-sm-1, + .mx-sm-1 { + margin-left: .25rem!important + } + .m-sm-2 { + margin: .5rem!important + } + .mt-sm-2, + .my-sm-2 { + margin-top: .5rem!important + } + .mr-sm-2, + .mx-sm-2 { + margin-right: .5rem!important + } + .mb-sm-2, + .my-sm-2 { + margin-bottom: .5rem!important + } + .ml-sm-2, + .mx-sm-2 { + margin-left: .5rem!important + } + .m-sm-3 { + margin: 1rem!important + } + .mt-sm-3, + .my-sm-3 { + margin-top: 1rem!important + } + .mr-sm-3, + .mx-sm-3 { + margin-right: 1rem!important + } + .mb-sm-3, + .my-sm-3 { + margin-bottom: 1rem!important + } + .ml-sm-3, + .mx-sm-3 { + margin-left: 1rem!important + } + .m-sm-4 { + margin: 1.5rem!important + } + .mt-sm-4, + .my-sm-4 { + margin-top: 1.5rem!important + } + .mr-sm-4, + .mx-sm-4 { + margin-right: 1.5rem!important + } + .mb-sm-4, + .my-sm-4 { + margin-bottom: 1.5rem!important + } + .ml-sm-4, + .mx-sm-4 { + margin-left: 1.5rem!important + } + .m-sm-5 { + margin: 3rem!important + } + .mt-sm-5, + .my-sm-5 { + margin-top: 3rem!important + } + .mr-sm-5, + .mx-sm-5 { + margin-right: 3rem!important + } + .mb-sm-5, + .my-sm-5 { + margin-bottom: 3rem!important + } + .ml-sm-5, + .mx-sm-5 { + margin-left: 3rem!important + } + .p-sm-0 { + padding: 0!important + } + .pt-sm-0, + .py-sm-0 { + padding-top: 0!important + } + .pr-sm-0, + .px-sm-0 { + padding-right: 0!important + } + .pb-sm-0, + .py-sm-0 { + padding-bottom: 0!important + } + .pl-sm-0, + .px-sm-0 { + padding-left: 0!important + } + .p-sm-1 { + padding: .25rem!important + } + .pt-sm-1, + .py-sm-1 { + padding-top: .25rem!important + } + .pr-sm-1, + .px-sm-1 { + padding-right: .25rem!important + } + .pb-sm-1, + .py-sm-1 { + padding-bottom: .25rem!important + } + .pl-sm-1, + .px-sm-1 { + padding-left: .25rem!important + } + .p-sm-2 { + padding: .5rem!important + } + .pt-sm-2, + .py-sm-2 { + padding-top: .5rem!important + } + .pr-sm-2, + .px-sm-2 { + padding-right: .5rem!important + } + .pb-sm-2, + .py-sm-2 { + padding-bottom: .5rem!important + } + .pl-sm-2, + .px-sm-2 { + padding-left: .5rem!important + } + .p-sm-3 { + padding: 1rem!important + } + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem!important + } + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem!important + } + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem!important + } + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem!important + } + .p-sm-4 { + padding: 1.5rem!important + } + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem!important + } + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem!important + } + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem!important + } + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem!important + } + .p-sm-5 { + padding: 3rem!important + } + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem!important + } + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem!important + } + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem!important + } + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem!important + } + .m-sm-auto { + margin: auto!important + } + .mt-sm-auto, + .my-sm-auto { + margin-top: auto!important + } + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto!important + } + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto!important + } + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto!important + } +} + +@media (min-width: 768px) { + .float-md-left { + float: left!important + } + .float-md-right { + float: right!important + } + .float-md-none { + float: none!important + } + .m-md-0 { + margin: 0!important + } + .mt-md-0, + .my-md-0 { + margin-top: 0!important + } + .mr-md-0, + .mx-md-0 { + margin-right: 0!important + } + .mb-md-0, + .my-md-0 { + margin-bottom: 0!important + } + .ml-md-0, + .mx-md-0 { + margin-left: 0!important + } + .m-md-1 { + margin: .25rem!important + } + .mt-md-1, + .my-md-1 { + margin-top: .25rem!important + } + .mr-md-1, + .mx-md-1 { + margin-right: .25rem!important + } + .mb-md-1, + .my-md-1 { + margin-bottom: .25rem!important + } + .ml-md-1, + .mx-md-1 { + margin-left: .25rem!important + } + .m-md-2 { + margin: .5rem!important + } + .mt-md-2, + .my-md-2 { + margin-top: .5rem!important + } + .mr-md-2, + .mx-md-2 { + margin-right: .5rem!important + } + .mb-md-2, + .my-md-2 { + margin-bottom: .5rem!important + } + .ml-md-2, + .mx-md-2 { + margin-left: .5rem!important + } + .m-md-3 { + margin: 1rem!important + } + .mt-md-3, + .my-md-3 { + margin-top: 1rem!important + } + .mr-md-3, + .mx-md-3 { + margin-right: 1rem!important + } + .mb-md-3, + .my-md-3 { + margin-bottom: 1rem!important + } + .ml-md-3, + .mx-md-3 { + margin-left: 1rem!important + } + .m-md-4 { + margin: 1.5rem!important + } + .mt-md-4, + .my-md-4 { + margin-top: 1.5rem!important + } + .mr-md-4, + .mx-md-4 { + margin-right: 1.5rem!important + } + .mb-md-4, + .my-md-4 { + margin-bottom: 1.5rem!important + } + .ml-md-4, + .mx-md-4 { + margin-left: 1.5rem!important + } + .m-md-5 { + margin: 3rem!important + } + .mt-md-5, + .my-md-5 { + margin-top: 3rem!important + } + .mr-md-5, + .mx-md-5 { + margin-right: 3rem!important + } + .mb-md-5, + .my-md-5 { + margin-bottom: 3rem!important + } + .ml-md-5, + .mx-md-5 { + margin-left: 3rem!important + } + .p-md-0 { + padding: 0!important + } + .pt-md-0, + .py-md-0 { + padding-top: 0!important + } + .pr-md-0, + .px-md-0 { + padding-right: 0!important + } + .pb-md-0, + .py-md-0 { + padding-bottom: 0!important + } + .pl-md-0, + .px-md-0 { + padding-left: 0!important + } + .p-md-1 { + padding: .25rem!important + } + .pt-md-1, + .py-md-1 { + padding-top: .25rem!important + } + .pr-md-1, + .px-md-1 { + padding-right: .25rem!important + } + .pb-md-1, + .py-md-1 { + padding-bottom: .25rem!important + } + .pl-md-1, + .px-md-1 { + padding-left: .25rem!important + } + .p-md-2 { + padding: .5rem!important + } + .pt-md-2, + .py-md-2 { + padding-top: .5rem!important + } + .pr-md-2, + .px-md-2 { + padding-right: .5rem!important + } + .pb-md-2, + .py-md-2 { + padding-bottom: .5rem!important + } + .pl-md-2, + .px-md-2 { + padding-left: .5rem!important + } + .p-md-3 { + padding: 1rem!important + } + .pt-md-3, + .py-md-3 { + padding-top: 1rem!important + } + .pr-md-3, + .px-md-3 { + padding-right: 1rem!important + } + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem!important + } + .pl-md-3, + .px-md-3 { + padding-left: 1rem!important + } + .p-md-4 { + padding: 1.5rem!important + } + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem!important + } + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem!important + } + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem!important + } + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem!important + } + .p-md-5 { + padding: 3rem!important + } + .pt-md-5, + .py-md-5 { + padding-top: 3rem!important + } + .pr-md-5, + .px-md-5 { + padding-right: 3rem!important + } + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem!important + } + .pl-md-5, + .px-md-5 { + padding-left: 3rem!important + } + .m-md-auto { + margin: auto!important + } + .mt-md-auto, + .my-md-auto { + margin-top: auto!important + } + .mr-md-auto, + .mx-md-auto { + margin-right: auto!important + } + .mb-md-auto, + .my-md-auto { + margin-bottom: auto!important + } + .ml-md-auto, + .mx-md-auto { + margin-left: auto!important + } +} + +@media (min-width: 992px) { + .float-lg-left { + float: left!important + } + .float-lg-right { + float: right!important + } + .float-lg-none { + float: none!important + } + .m-lg-0 { + margin: 0!important + } + .mt-lg-0, + .my-lg-0 { + margin-top: 0!important + } + .mr-lg-0, + .mx-lg-0 { + margin-right: 0!important + } + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0!important + } + .ml-lg-0, + .mx-lg-0 { + margin-left: 0!important + } + .m-lg-1 { + margin: .25rem!important + } + .mt-lg-1, + .my-lg-1 { + margin-top: .25rem!important + } + .mr-lg-1, + .mx-lg-1 { + margin-right: .25rem!important + } + .mb-lg-1, + .my-lg-1 { + margin-bottom: .25rem!important + } + .ml-lg-1, + .mx-lg-1 { + margin-left: .25rem!important + } + .m-lg-2 { + margin: .5rem!important + } + .mt-lg-2, + .my-lg-2 { + margin-top: .5rem!important + } + .mr-lg-2, + .mx-lg-2 { + margin-right: .5rem!important + } + .mb-lg-2, + .my-lg-2 { + margin-bottom: .5rem!important + } + .ml-lg-2, + .mx-lg-2 { + margin-left: .5rem!important + } + .m-lg-3 { + margin: 1rem!important + } + .mt-lg-3, + .my-lg-3 { + margin-top: 1rem!important + } + .mr-lg-3, + .mx-lg-3 { + margin-right: 1rem!important + } + .mb-lg-3, + .my-lg-3 { + margin-bottom: 1rem!important + } + .ml-lg-3, + .mx-lg-3 { + margin-left: 1rem!important + } + .m-lg-4 { + margin: 1.5rem!important + } + .mt-lg-4, + .my-lg-4 { + margin-top: 1.5rem!important + } + .mr-lg-4, + .mx-lg-4 { + margin-right: 1.5rem!important + } + .mb-lg-4, + .my-lg-4 { + margin-bottom: 1.5rem!important + } + .ml-lg-4, + .mx-lg-4 { + margin-left: 1.5rem!important + } + .m-lg-5 { + margin: 3rem!important + } + .mt-lg-5, + .my-lg-5 { + margin-top: 3rem!important + } + .mr-lg-5, + .mx-lg-5 { + margin-right: 3rem!important + } + .mb-lg-5, + .my-lg-5 { + margin-bottom: 3rem!important + } + .ml-lg-5, + .mx-lg-5 { + margin-left: 3rem!important + } + .p-lg-0 { + padding: 0!important + } + .pt-lg-0, + .py-lg-0 { + padding-top: 0!important + } + .pr-lg-0, + .px-lg-0 { + padding-right: 0!important + } + .pb-lg-0, + .py-lg-0 { + padding-bottom: 0!important + } + .pl-lg-0, + .px-lg-0 { + padding-left: 0!important + } + .p-lg-1 { + padding: .25rem!important + } + .pt-lg-1, + .py-lg-1 { + padding-top: .25rem!important + } + .pr-lg-1, + .px-lg-1 { + padding-right: .25rem!important + } + .pb-lg-1, + .py-lg-1 { + padding-bottom: .25rem!important + } + .pl-lg-1, + .px-lg-1 { + padding-left: .25rem!important + } + .p-lg-2 { + padding: .5rem!important + } + .pt-lg-2, + .py-lg-2 { + padding-top: .5rem!important + } + .pr-lg-2, + .px-lg-2 { + padding-right: .5rem!important + } + .pb-lg-2, + .py-lg-2 { + padding-bottom: .5rem!important + } + .pl-lg-2, + .px-lg-2 { + padding-left: .5rem!important + } + .p-lg-3 { + padding: 1rem!important + } + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem!important + } + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem!important + } + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem!important + } + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem!important + } + .p-lg-4 { + padding: 1.5rem!important + } + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem!important + } + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem!important + } + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem!important + } + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem!important + } + .p-lg-5 { + padding: 3rem!important + } + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem!important + } + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem!important + } + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem!important + } + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem!important + } + .m-lg-auto { + margin: auto!important + } + .mt-lg-auto, + .my-lg-auto { + margin-top: auto!important + } + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto!important + } + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto!important + } + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto!important + } +} + +@media (min-width: 1200px) { + .float-xl-left { + float: left!important + } + .float-xl-right { + float: right!important + } + .float-xl-none { + float: none!important + } + .m-xl-0 { + margin: 0!important + } + .mt-xl-0, + .my-xl-0 { + margin-top: 0!important + } + .mr-xl-0, + .mx-xl-0 { + margin-right: 0!important + } + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0!important + } + .ml-xl-0, + .mx-xl-0 { + margin-left: 0!important + } + .m-xl-1 { + margin: .25rem!important + } + .mt-xl-1, + .my-xl-1 { + margin-top: .25rem!important + } + .mr-xl-1, + .mx-xl-1 { + margin-right: .25rem!important + } + .mb-xl-1, + .my-xl-1 { + margin-bottom: .25rem!important + } + .ml-xl-1, + .mx-xl-1 { + margin-left: .25rem!important + } + .m-xl-2 { + margin: .5rem!important + } + .mt-xl-2, + .my-xl-2 { + margin-top: .5rem!important + } + .mr-xl-2, + .mx-xl-2 { + margin-right: .5rem!important + } + .mb-xl-2, + .my-xl-2 { + margin-bottom: .5rem!important + } + .ml-xl-2, + .mx-xl-2 { + margin-left: .5rem!important + } + .m-xl-3 { + margin: 1rem!important + } + .mt-xl-3, + .my-xl-3 { + margin-top: 1rem!important + } + .mr-xl-3, + .mx-xl-3 { + margin-right: 1rem!important + } + .mb-xl-3, + .my-xl-3 { + margin-bottom: 1rem!important + } + .ml-xl-3, + .mx-xl-3 { + margin-left: 1rem!important + } + .m-xl-4 { + margin: 1.5rem!important + } + .mt-xl-4, + .my-xl-4 { + margin-top: 1.5rem!important + } + .mr-xl-4, + .mx-xl-4 { + margin-right: 1.5rem!important + } + .mb-xl-4, + .my-xl-4 { + margin-bottom: 1.5rem!important + } + .ml-xl-4, + .mx-xl-4 { + margin-left: 1.5rem!important + } + .m-xl-5 { + margin: 3rem!important + } + .mt-xl-5, + .my-xl-5 { + margin-top: 3rem!important + } + .mr-xl-5, + .mx-xl-5 { + margin-right: 3rem!important + } + .mb-xl-5, + .my-xl-5 { + margin-bottom: 3rem!important + } + .ml-xl-5, + .mx-xl-5 { + margin-left: 3rem!important + } + .p-xl-0 { + padding: 0!important + } + .pt-xl-0, + .py-xl-0 { + padding-top: 0!important + } + .pr-xl-0, + .px-xl-0 { + padding-right: 0!important + } + .pb-xl-0, + .py-xl-0 { + padding-bottom: 0!important + } + .pl-xl-0, + .px-xl-0 { + padding-left: 0!important + } + .p-xl-1 { + padding: .25rem!important + } + .pt-xl-1, + .py-xl-1 { + padding-top: .25rem!important + } + .pr-xl-1, + .px-xl-1 { + padding-right: .25rem!important + } + .pb-xl-1, + .py-xl-1 { + padding-bottom: .25rem!important + } + .pl-xl-1, + .px-xl-1 { + padding-left: .25rem!important + } + .p-xl-2 { + padding: .5rem!important + } + .pt-xl-2, + .py-xl-2 { + padding-top: .5rem!important + } + .pr-xl-2, + .px-xl-2 { + padding-right: .5rem!important + } + .pb-xl-2, + .py-xl-2 { + padding-bottom: .5rem!important + } + .pl-xl-2, + .px-xl-2 { + padding-left: .5rem!important + } + .p-xl-3 { + padding: 1rem!important + } + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem!important + } + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem!important + } + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem!important + } + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem!important + } + .p-xl-4 { + padding: 1.5rem!important + } + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem!important + } + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem!important + } + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem!important + } + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem!important + } + .p-xl-5 { + padding: 3rem!important + } + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem!important + } + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem!important + } + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem!important + } + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem!important + } + .m-xl-auto { + margin: auto!important + } + .mt-xl-auto, + .my-xl-auto { + margin-top: auto!important + } + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto!important + } + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto!important + } + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto!important + } +} + +.mt-0, +.my-0 { + margin-top: 0!important +} + +.mr-0, +.mx-0 { + margin-right: 0!important +} + +.mb-0, +.my-0 { + margin-bottom: 0!important +} + +.ml-0, +.mx-0 { + margin-left: 0!important +} + +.text-justify { + text-align: justify!important +} + +.text-nowrap { + white-space: nowrap!important +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.text-left { + text-align: left!important +} + +.text-right { + text-align: right!important +} + +.text-center { + text-align: center!important +} + +@media (min-width: 576px) { + .text-sm-left { + text-align: left!important + } + .text-sm-right { + text-align: right!important + } + .text-sm-center { + text-align: center!important + } +} + +@media (min-width: 768px) { + .text-md-left { + text-align: left!important + } + .text-md-right { + text-align: right!important + } + .text-md-center { + text-align: center!important + } +} + +@media (min-width: 992px) { + .text-lg-left { + text-align: left!important + } + .text-lg-right { + text-align: right!important + } + .text-lg-center { + text-align: center!important + } +} + +@media (min-width: 1200px) { + .text-xl-left { + text-align: left!important + } + .text-xl-right { + text-align: right!important + } + .text-xl-center { + text-align: center!important + } +} + +.text-lowercase { + text-transform: lowercase!important +} + +.text-uppercase { + text-transform: uppercase!important +} + +.text-capitalize { + text-transform: capitalize!important +} + +.btn, +.classic-tabs li a, +.font-up, +footer.page-footer .title { + text-transform: uppercase +} + +.font-weight-light { + font-weight: 300!important +} + +.font-weight-normal { + font-weight: 400!important +} + +.font-weight-bold { + font-weight: 700!important +} + +.font-italic { + font-style: italic!important +} + +.text-white { + color: #fff!important +} + +.text-primary { + color: #007bff!important +} + +a.text-primary:focus, +a.text-primary:hover { + color: #0062cc!important +} + +.text-secondary { + color: #868e96!important +} + +a.text-secondary:focus, +a.text-secondary:hover { + color: #6c757d!important +} + +.text-success { + color: #28a745!important +} + +a.text-success:focus, +a.text-success:hover { + color: #1e7e34!important +} + +.text-info { + color: #17a2b8!important +} + +a.text-info:focus, +a.text-info:hover { + color: #117a8b!important +} + +.text-warning { + color: #ffc107!important +} + +a.text-warning:focus, +a.text-warning:hover { + color: #d39e00!important +} + +.text-danger { + color: #dc3545!important +} + +a.text-danger:focus, +a.text-danger:hover { + color: #bd2130!important +} + +.text-light { + color: #f8f9fa!important +} + +a.text-light:focus, +a.text-light:hover { + color: #dae0e5!important +} + +.text-dark { + color: #343a40!important +} + +a.text-dark:focus, +a.text-dark:hover { + color: #1d2124!important +} + +.text-muted { + color: #868e96!important +} + +.text-hide { + font: 0/0 a; + color: transparent; + background-color: transparent; + border: 0 +} + +.visible { + visibility: visible!important +} + +.invisible { + visibility: hidden!important +} + +.mdb-color.lighten-5 { + background-color: #D0D6E2!important +} + +.mdb-color.lighten-4 { + background-color: #B1BACE!important +} + +.mdb-color.lighten-3 { + background-color: #929FBA!important +} + +.mdb-color.lighten-2 { + background-color: #7283A7!important +} + +.mdb-color.lighten-1 { + background-color: #59698D!important +} + +.mdb-color-text { + color: #45526E!important +} + +.mdb-color.darken-1 { + background-color: #3B465E!important +} + +.mdb-color.darken-2 { + background-color: #2E3951!important +} + +.mdb-color.darken-3 { + background-color: #1C2A48!important +} + +.mdb-color.darken-4 { + background-color: #1C2331!important +} + +.red.lighten-5 { + background-color: #FFEBEE!important +} + +.red.lighten-4 { + background-color: #FFCDD2!important +} + +.red.lighten-3 { + background-color: #EF9A9A!important +} + +.red.lighten-2 { + background-color: #E57373!important +} + +.red.lighten-1 { + background-color: #EF5350!important +} + +.red { + background-color: #F44336!important +} + +.red-text { + color: #F44336!important +} + +.red.darken-1 { + background-color: #E53935!important +} + +.red.darken-2 { + background-color: #D32F2F!important +} + +.red.darken-3 { + background-color: #C62828!important +} + +.red.darken-4 { + background-color: #B71C1C!important +} + +.red.accent-1 { + background-color: #FF8A80!important +} + +.red.accent-2 { + background-color: #FF5252!important +} + +.red.accent-3 { + background-color: #FF1744!important +} + +.red.accent-4 { + background-color: #D50000!important +} + +.pink.lighten-5 { + background-color: #fce4ec!important +} + +.pink.lighten-4 { + background-color: #f8bbd0!important +} + +.pink.lighten-3 { + background-color: #f48fb1!important +} + +.pink.lighten-2 { + background-color: #f06292!important +} + +.pink.lighten-1 { + background-color: #ec407a!important +} + +.pink { + background-color: #e91e63!important +} + +.pink-text { + color: #e91e63!important +} + +.pink.darken-1 { + background-color: #d81b60!important +} + +.pink.darken-2 { + background-color: #c2185b!important +} + +.pink.darken-3 { + background-color: #ad1457!important +} + +.pink.darken-4 { + background-color: #880e4f!important +} + +.pink.accent-1 { + background-color: #ff80ab!important +} + +.pink.accent-2 { + background-color: #ff4081!important +} + +.pink.accent-3 { + background-color: #f50057!important +} + +.pink.accent-4 { + background-color: #c51162!important +} + +.purple.lighten-5 { + background-color: #f3e5f5!important +} + +.purple.lighten-4 { + background-color: #e1bee7!important +} + +.purple.lighten-3 { + background-color: #ce93d8!important +} + +.purple.lighten-2 { + background-color: #ba68c8!important +} + +.purple.lighten-1 { + background-color: #ab47bc!important +} + +.purple { + background-color: #9c27b0!important +} + +.purple-text { + color: #9c27b0!important +} + +.purple.darken-1 { + background-color: #8e24aa!important +} + +.purple.darken-2 { + background-color: #7b1fa2!important +} + +.purple.darken-3 { + background-color: #6a1b9a!important +} + +.purple.darken-4 { + background-color: #4a148c!important +} + +.purple.accent-1 { + background-color: #ea80fc!important +} + +.purple.accent-2 { + background-color: #e040fb!important +} + +.purple.accent-3 { + background-color: #d500f9!important +} + +.purple.accent-4 { + background-color: #a0f!important +} + +.deep-purple.lighten-5 { + background-color: #ede7f6!important +} + +.deep-purple.lighten-4 { + background-color: #d1c4e9!important +} + +.deep-purple.lighten-3 { + background-color: #b39ddb!important +} + +.deep-purple.lighten-2 { + background-color: #9575cd!important +} + +.deep-purple.lighten-1 { + background-color: #7e57c2!important +} + +.deep-purple { + background-color: #673ab7!important +} + +.deep-purple-text { + color: #673ab7!important +} + +.deep-purple.darken-1 { + background-color: #5e35b1!important +} + +.deep-purple.darken-2 { + background-color: #512da8!important +} + +.deep-purple.darken-3 { + background-color: #4527a0!important +} + +.deep-purple.darken-4 { + background-color: #311b92!important +} + +.deep-purple.accent-1 { + background-color: #b388ff!important +} + +.deep-purple.accent-2 { + background-color: #7c4dff!important +} + +.deep-purple.accent-3 { + background-color: #651fff!important +} + +.deep-purple.accent-4 { + background-color: #6200ea!important +} + +.indigo.lighten-5 { + background-color: #e8eaf6!important +} + +.indigo.lighten-4 { + background-color: #c5cae9!important +} + +.indigo.lighten-3 { + background-color: #9fa8da!important +} + +.indigo.lighten-2 { + background-color: #7986cb!important +} + +.indigo.lighten-1 { + background-color: #5c6bc0!important +} + +.indigo { + background-color: #3f51b5!important +} + +.indigo-text { + color: #3f51b5!important +} + +.indigo.darken-1 { + background-color: #3949ab!important +} + +.indigo.darken-2 { + background-color: #303f9f!important +} + +.indigo.darken-3 { + background-color: #283593!important +} + +.indigo.darken-4 { + background-color: #1a237e!important +} + +.indigo.accent-1 { + background-color: #8c9eff!important +} + +.indigo.accent-2 { + background-color: #536dfe!important +} + +.indigo.accent-3 { + background-color: #3d5afe!important +} + +.indigo.accent-4 { + background-color: #304ffe!important +} + +.blue.lighten-5 { + background-color: #E3F2FD!important +} + +.blue.lighten-4 { + background-color: #BBDEFB!important +} + +.blue.lighten-3 { + background-color: #90CAF9!important +} + +.blue.lighten-2 { + background-color: #64B5F6!important +} + +.blue.lighten-1 { + background-color: #42A5F5!important +} + +.blue { + background-color: #2196F3!important +} + +.blue-text { + color: #2196F3!important +} + +.blue.darken-1 { + background-color: #1E88E5!important +} + +.blue.darken-2 { + background-color: #1976D2!important +} + +.blue.darken-3 { + background-color: #1565C0!important +} + +.blue.darken-4 { + background-color: #0D47A1!important +} + +.blue.accent-1 { + background-color: #82B1FF!important +} + +.blue.accent-2 { + background-color: #448AFF!important +} + +.blue.accent-3 { + background-color: #2979FF!important +} + +.blue.accent-4 { + background-color: #2962FF!important +} + +.light-blue.lighten-5 { + background-color: #e1f5fe!important +} + +.light-blue.lighten-4 { + background-color: #b3e5fc!important +} + +.light-blue.lighten-3 { + background-color: #81d4fa!important +} + +.light-blue.lighten-2 { + background-color: #4fc3f7!important +} + +.light-blue.lighten-1 { + background-color: #29b6f6!important +} + +.light-blue { + background-color: #03a9f4!important +} + +.light-blue.darken-1 { + background-color: #039be5!important +} + +.light-blue.darken-2 { + background-color: #0288d1!important +} + +.light-blue.darken-3 { + background-color: #0277bd!important +} + +.light-blue.darken-4 { + background-color: #01579b!important +} + +.light-blue.accent-1 { + background-color: #80d8ff!important +} + +.light-blue.accent-2 { + background-color: #40c4ff!important +} + +.light-blue.accent-3 { + background-color: #00b0ff!important +} + +.light-blue.accent-4 { + background-color: #0091ea!important +} + +.cyan.lighten-5 { + background-color: #e0f7fa!important +} + +.cyan.lighten-4 { + background-color: #b2ebf2!important +} + +.cyan.lighten-3 { + background-color: #80deea!important +} + +.cyan.lighten-2 { + background-color: #4dd0e1!important +} + +.cyan.lighten-1 { + background-color: #26c6da!important +} + +.cyan { + background-color: #00bcd4!important +} + +.cyan-text { + color: #00bcd4!important +} + +.cyan.darken-1 { + background-color: #00acc1!important +} + +.cyan.darken-2 { + background-color: #0097a7!important +} + +.cyan.darken-3 { + background-color: #00838f!important +} + +.cyan.darken-4 { + background-color: #006064!important +} + +.cyan.accent-1 { + background-color: #84ffff!important +} + +.cyan.accent-2 { + background-color: #18ffff!important +} + +.cyan.accent-3 { + background-color: #00e5ff!important +} + +.cyan.accent-4 { + background-color: #00b8d4!important +} + +.teal.lighten-5 { + background-color: #e0f2f1!important +} + +.teal.lighten-4 { + background-color: #b2dfdb!important +} + +.teal.lighten-3 { + background-color: #80cbc4!important +} + +.teal.lighten-2 { + background-color: #4db6ac!important +} + +.teal.lighten-1 { + background-color: #26a69a!important +} + +.teal { + background-color: #009688!important +} + +.teal-text { + color: #009688!important +} + +.teal.darken-1 { + background-color: #00897b!important +} + +.teal.darken-2 { + background-color: #00796b!important +} + +.teal.darken-3 { + background-color: #00695c!important +} + +.teal.darken-4 { + background-color: #004d40!important +} + +.teal.accent-1 { + background-color: #a7ffeb!important +} + +.teal.accent-2 { + background-color: #64ffda!important +} + +.teal.accent-3 { + background-color: #1de9b6!important +} + +.teal.accent-4 { + background-color: #00bfa5!important +} + +.green.lighten-5 { + background-color: #E8F5E9!important +} + +.green.lighten-4 { + background-color: #C8E6C9!important +} + +.green.lighten-3 { + background-color: #A5D6A7!important +} + +.green.lighten-2 { + background-color: #81C784!important +} + +.green.lighten-1 { + background-color: #66BB6A!important +} + +.green { + background-color: #4CAF50!important +} + +.green-text { + color: #4CAF50!important +} + +.green.darken-1 { + background-color: #43A047!important +} + +.green.darken-2 { + background-color: #388E3C!important +} + +.green.darken-3 { + background-color: #2E7D32!important +} + +.green.darken-4 { + background-color: #1B5E20!important +} + +.green.accent-1 { + background-color: #B9F6CA!important +} + +.green.accent-2 { + background-color: #69F0AE!important +} + +.green.accent-3 { + background-color: #00E676!important +} + +.green.accent-4 { + background-color: #00C853!important +} + +.light-green.lighten-5 { + background-color: #f1f8e9!important +} + +.light-green.lighten-4 { + background-color: #dcedc8!important +} + +.light-green.lighten-3 { + background-color: #c5e1a5!important +} + +.light-green.lighten-2 { + background-color: #aed581!important +} + +.light-green.lighten-1 { + background-color: #9ccc65!important +} + +.light-green { + background-color: #8bc34a!important +} + +.light-green-text { + color: #8bc34a!important +} + +.light-green.darken-1 { + background-color: #7cb342!important +} + +.light-green.darken-2 { + background-color: #689f38!important +} + +.light-green.darken-3 { + background-color: #558b2f!important +} + +.light-green.darken-4 { + background-color: #33691e!important +} + +.light-green.accent-1 { + background-color: #ccff90!important +} + +.light-green.accent-2 { + background-color: #b2ff59!important +} + +.light-green.accent-3 { + background-color: #76ff03!important +} + +.light-green.accent-4 { + background-color: #64dd17!important +} + +.lime.lighten-5 { + background-color: #f9fbe7!important +} + +.lime.lighten-4 { + background-color: #f0f4c3!important +} + +.lime.lighten-3 { + background-color: #e6ee9c!important +} + +.lime.lighten-2 { + background-color: #dce775!important +} + +.lime.lighten-1 { + background-color: #d4e157!important +} + +.lime { + background-color: #cddc39!important +} + +.lime-text { + color: #cddc39!important +} + +.lime.darken-1 { + background-color: #c0ca33!important +} + +.lime.darken-2 { + background-color: #afb42b!important +} + +.lime.darken-3 { + background-color: #9e9d24!important +} + +.lime.darken-4 { + background-color: #827717!important +} + +.lime.accent-1 { + background-color: #f4ff81!important +} + +.lime.accent-2 { + background-color: #eeff41!important +} + +.lime.accent-3 { + background-color: #c6ff00!important +} + +.lime.accent-4 { + background-color: #aeea00!important +} + +.yellow.lighten-5 { + background-color: #fffde7!important +} + +.yellow.lighten-4 { + background-color: #fff9c4!important +} + +.yellow.lighten-3 { + background-color: #fff59d!important +} + +.yellow.lighten-2 { + background-color: #fff176!important +} + +.yellow.lighten-1 { + background-color: #ffee58!important +} + +.yellow { + background-color: #ffeb3b!important +} + +.yellow-text { + color: #ffeb3b!important +} + +.yellow.darken-1 { + background-color: #fdd835!important +} + +.yellow.darken-2 { + background-color: #fbc02d!important +} + +.yellow.darken-3 { + background-color: #f9a825!important +} + +.yellow.darken-4 { + background-color: #f57f17!important +} + +.yellow.accent-1 { + background-color: #ffff8d!important +} + +.yellow.accent-2 { + background-color: #ff0!important +} + +.yellow.accent-3 { + background-color: #ffea00!important +} + +.yellow.accent-4 { + background-color: #ffd600!important +} + +.amber.lighten-5 { + background-color: #fff8e1!important +} + +.amber.lighten-4 { + background-color: #ffecb3!important +} + +.amber.lighten-3 { + background-color: #ffe082!important +} + +.amber.lighten-2 { + background-color: #ffd54f!important +} + +.amber.lighten-1 { + background-color: #ffca28!important +} + +.amber { + background-color: #ffc107!important +} + +.amber-text { + color: #ffc107!important +} + +.amber.darken-1 { + background-color: #ffb300!important +} + +.amber.darken-2 { + background-color: #ffa000!important +} + +.amber.darken-3 { + background-color: #ff8f00!important +} + +.amber.darken-4 { + background-color: #ff6f00!important +} + +.amber.accent-1 { + background-color: #ffe57f!important +} + +.amber.accent-2 { + background-color: #ffd740!important +} + +.amber.accent-3 { + background-color: #ffc400!important +} + +.amber.accent-4 { + background-color: #ffab00!important +} + +.orange.lighten-5 { + background-color: #fff3e0!important +} + +.orange.lighten-4 { + background-color: #ffe0b2!important +} + +.orange.lighten-3 { + background-color: #ffcc80!important +} + +.orange.lighten-2 { + background-color: #ffb74d!important +} + +.orange.lighten-1 { + background-color: #ffa726!important +} + +.orange { + background-color: #ff9800!important +} + +.orange-text { + color: #ff9800!important +} + +.orange.darken-1 { + background-color: #fb8c00!important +} + +.orange.darken-2 { + background-color: #f57c00!important +} + +.orange.darken-3 { + background-color: #ef6c00!important +} + +.orange.darken-4 { + background-color: #e65100!important +} + +.orange.accent-1 { + background-color: #ffd180!important +} + +.orange.accent-2 { + background-color: #ffab40!important +} + +.orange.accent-3 { + background-color: #ff9100!important +} + +.orange.accent-4 { + background-color: #ff6d00!important +} + +.deep-orange.lighten-5 { + background-color: #fbe9e7!important +} + +.deep-orange.lighten-4 { + background-color: #ffccbc!important +} + +.deep-orange.lighten-3 { + background-color: #ffab91!important +} + +.deep-orange.lighten-2 { + background-color: #ff8a65!important +} + +.deep-orange.lighten-1 { + background-color: #ff7043!important +} + +.deep-orange { + background-color: #ff5722!important +} + +.deep-orange-text { + color: #ff5722!important +} + +.deep-orange.darken-1 { + background-color: #f4511e!important +} + +.deep-orange.darken-2 { + background-color: #e64a19!important +} + +.deep-orange.darken-3 { + background-color: #d84315!important +} + +.deep-orange.darken-4 { + background-color: #bf360c!important +} + +.deep-orange.accent-1 { + background-color: #ff9e80!important +} + +.deep-orange.accent-2 { + background-color: #ff6e40!important +} + +.deep-orange.accent-3 { + background-color: #ff3d00!important +} + +.deep-orange.accent-4 { + background-color: #dd2c00!important +} + +.brown.lighten-5 { + background-color: #efebe9!important +} + +.brown.lighten-4 { + background-color: #d7ccc8!important +} + +.brown.lighten-3 { + background-color: #bcaaa4!important +} + +.brown.lighten-2 { + background-color: #a1887f!important +} + +.brown.lighten-1 { + background-color: #8d6e63!important +} + +.brown { + background-color: #795548!important +} + +.brown-text { + color: #795548!important +} + +.brown.darken-1 { + background-color: #6d4c41!important +} + +.brown.darken-2 { + background-color: #5d4037!important +} + +.brown.darken-3 { + background-color: #4e342e!important +} + +.brown.darken-4 { + background-color: #3e2723!important +} + +.blue-grey.lighten-5 { + background-color: #eceff1!important +} + +.blue-grey.lighten-4 { + background-color: #cfd8dc!important +} + +.blue-grey.lighten-3 { + background-color: #b0bec5!important +} + +.blue-grey.lighten-2 { + background-color: #90a4ae!important +} + +.blue-grey.lighten-1 { + background-color: #78909c!important +} + +.blue-grey { + background-color: #607d8b!important +} + +.blue-grey-text { + color: #607d8b!important +} + +.blue-grey.darken-1 { + background-color: #546e7a!important +} + +.blue-grey.darken-2 { + background-color: #455a64!important +} + +.blue-grey.darken-3 { + background-color: #37474f!important +} + +.blue-grey.darken-4 { + background-color: #263238!important +} + +.grey.lighten-5 { + background-color: #fafafa!important +} + +.grey.lighten-4 { + background-color: #f5f5f5!important +} + +.grey.lighten-3 { + background-color: #eee!important +} + +.grey.lighten-2 { + background-color: #e0e0e0!important +} + +.grey.lighten-1 { + background-color: #bdbdbd!important +} + +.grey { + background-color: #9e9e9e!important +} + +.grey-text { + color: #9e9e9e!important +} + +.grey.darken-1 { + background-color: #757575!important +} + +.grey.darken-2 { + background-color: #616161!important +} + +.grey.darken-3 { + background-color: #424242!important +} + +.grey.darken-4 { + background-color: #212121!important +} + +.card .shades.card-review, +.shades.black, +.shades.picker__list-item:hover { + background-color: #000!important +} + +.card .shades.card-reveal, +.card-wrapper .shades.face, +.carousel-thumbnails .carousel-indicators .shades.active, +.picker__box .picker__header .shades.picker__select--month.browser-default, +.picker__box .picker__header .shades.picker__select--year.browser-default, +.shades.picker__list-item, +.shades.white, +.testimonial-card .shades.avatar { + background-color: #FFF!important +} + +.shades.transparent { + background-color: transparent!important +} + +.black, +.card .card-review, +.picker__list-item:hover { + background-color: #000!important +} + +.black-text, +.btn-link, +.card .activator, +.card-wrapper .face .content .rotate-btn, +.toast-close-button:focus, +.toast-close-button:hover { + color: #000!important +} + +.card .card-reveal, +.card-wrapper .face, +.carousel-thumbnails .carousel-indicators .active, +.picker__box .picker__header .picker__select--month.browser-default, +.picker__box .picker__header .picker__select--year.browser-default, +.picker__list-item, +.testimonial-card .avatar, +.white { + background-color: #FFF!important +} + +#toast-container>div, +.btn, +.card.card-cascade .view.gradient-card-header, +.card.card-dark .activator, +.card.card-dark .card-body, +.card.card-dark .card-body a, +.clockpicker-display .clockpicker-display-column #click-am.text-primary, +.clockpicker-display .clockpicker-display-column #click-pm.text-primary, +.clockpicker-display .clockpicker-display-column .clockpicker-span-hours.text-primary, +.clockpicker-display .clockpicker-display-column .clockpicker-span-minutes.text-primary, +.colorful-side-nav .collapsible a, +.colorful-side-nav .social a, +.colorful-side-nav p, +.dark-side-nav .collapsible a, +.dark-side-nav .social a, +.dark-side-nav p, +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-tick, +.darktheme .picker__box .picker__date-display .clockpicker-display, +.darktheme .picker__box .picker__date-display .clockpicker-display .clockpicker-span-am-pm, +.darktheme .picker__box .picker__footer button, +.dropdown .dropdown-menu .dropdown-item:active, +.dropdown .dropdown-menu .dropdown-item:hover, +.picker--focused .picker__list-item--selected, +.picker--time .picker__button--clear:focus, +.picker--time .picker__button--clear:focus:before, +.picker--time .picker__button--clear:hover, +.picker--time .picker__button--clear:hover:before, +.picker__box .picker__header .picker__date-display, +.picker__box .picker__table .picker--focused, +.picker__box .picker__table .picker__day--outfocus, +.picker__box .picker__table .picker__day--selected, +.picker__box .picker__table .picker__day--selected:hover, +.picker__date-display, +.picker__date-display .clockpicker-display .clockpicker-display-column #click-am.text-primary, +.picker__date-display .clockpicker-display .clockpicker-display-column #click-pm.text-primary, +.picker__date-display .clockpicker-display .clockpicker-display-column .clockpicker-span-hours.text-primary, +.picker__date-display .clockpicker-display .clockpicker-display-column .clockpicker-span-minutes.text-primary, +.picker__list-item--selected, +.picker__list-item--selected:hover, +.side-nav, +.side-nav .search-form .form-control, +.stylish-side-nav .collapsible a, +.stylish-side-nav .social a, +.stylish-side-nav p, +.toast-close-button, +.toast-message a, +.toast-message label, +.white-text, +section .contact { + color: #FFF!important +} + +.transparent { + background-color: transparent!important +} + +.transparent-text { + color: transparent!important +} + +.light-blue-text { + color: #82B1FF!important +} + +.dark-grey-text { + color: #4f4f4f!important +} + +.danger-color, +.stepper li.warning a .circle, +.toast-error { + background-color: #ff3547!important +} + +.danger-color-dark { + background-color: #C00!important +} + +.toast-warning, +.warning-color { + background-color: #fb3!important +} + +.warning-color-dark { + background-color: #F80!important +} + +.success-color, +.toast-success { + background-color: #00C851!important +} + +.success-color-dark { + background-color: #007E33!important +} + +.info-color, +.toast-info { + background-color: #33b5e5!important +} + +.info-color-dark { + background-color: #09C!important +} + +.default-color { + background-color: #2BBBAD!important +} + +.default-color-dark { + background-color: #00695c!important +} + +.primary-color, +.stepper li.active a .circle, +.stepper li.completed a .circle { + background-color: #4285F4!important +} + +.primary-color-dark { + background-color: #0d47a1!important +} + +.secondary-color { + background-color: #a6c!important +} + +.secondary-color-dark { + background-color: #93C!important +} + +.elegant-color { + background-color: #2E2E2E!important +} + +.elegant-color-dark { + background-color: #212121!important +} + +.stylish-color { + background-color: #4B515D!important +} + +.stylish-color-dark { + background-color: #3E4551!important +} + +.special-color { + background-color: #37474F!important +} + +.special-color-dark { + background-color: #263238!important +} + +.unique-color { + background-color: #3F729B!important +} + +.unique-color-dark { + background-color: #1C2331!important +} + +.mdb-color { + background-color: #45526E!important +} + +.rgba-blue-light { + background-color: rgba(3, 169, 244, .3)!important +} + +.rgba-red-light { + background-color: rgba(244, 67, 54, .3)!important +} + +.rgba-pink-light { + background-color: rgba(233, 30, 99, .3)!important +} + +.rgba-purple-light { + background-color: rgba(156, 39, 176, .3)!important +} + +.rgba-indigo-light { + background-color: rgba(63, 81, 181, .3)!important +} + +.rgba-cyan-light { + background-color: rgba(0, 188, 212, .3)!important +} + +.rgba-teal-light { + background-color: rgba(0, 150, 136, .3)!important +} + +.rgba-green-light { + background-color: rgba(76, 175, 80, .3)!important +} + +.rgba-lime-light { + background-color: rgba(205, 220, 57, .3)!important +} + +.rgba-yellow-light { + background-color: rgba(255, 235, 59, .3)!important +} + +.rgba-orange-light { + background-color: rgba(255, 152, 0, .3)!important +} + +.rgba-brown-light { + background-color: rgba(121, 85, 72, .3)!important +} + +.rgba-grey-light { + background-color: rgba(158, 158, 158, .3)!important +} + +.rgba-bluegrey-light { + background-color: rgba(96, 125, 139, .3)!important +} + +.rgba-black-light { + background-color: rgba(0, 0, 0, .3)!important +} + +.rgba-stylish-light { + background-color: rgba(62, 69, 81, .3)!important +} + +.rgba-white-light { + background-color: rgba(255, 255, 255, .3)!important +} + +.rgba-blue-strong { + background-color: rgba(3, 169, 244, .7)!important +} + +.rgba-red-strong { + background-color: rgba(244, 67, 54, .7)!important +} + +.rgba-pink-strong { + background-color: rgba(233, 30, 99, .7)!important +} + +.rgba-purple-strong { + background-color: rgba(156, 39, 176, .7)!important +} + +.rgba-indigo-strong { + background-color: rgba(63, 81, 181, .7)!important +} + +.rgba-cyan-strong { + background-color: rgba(0, 188, 212, .7)!important +} + +.rgba-teal-strong { + background-color: rgba(0, 150, 136, .7)!important +} + +.rgba-green-strong { + background-color: rgba(76, 175, 80, .7)!important +} + +.rgba-lime-strong { + background-color: rgba(205, 220, 57, .7)!important +} + +.rgba-yellow-strong { + background-color: rgba(255, 235, 59, .7)!important +} + +.rgba-orange-strong { + background-color: rgba(255, 152, 0, .7)!important +} + +.rgba-brown-strong { + background-color: rgba(121, 85, 72, .7)!important +} + +.rgba-grey-strong { + background-color: rgba(158, 158, 158, .7)!important +} + +.rgba-bluegrey-strong { + background-color: rgba(96, 125, 139, .7)!important +} + +.rgba-black-strong { + background-color: rgba(0, 0, 0, .7)!important +} + +.rgba-stylish-strong { + background-color: rgba(62, 69, 81, .7)!important +} + +.rgba-white-strong { + background-color: rgba(255, 255, 255, .7)!important +} + +.rgba-blue-slight { + background-color: rgba(3, 169, 244, .1)!important +} + +.rgba-red-slight { + background-color: rgba(244, 67, 54, .1)!important +} + +.rgba-pink-slight { + background-color: rgba(233, 30, 99, .1)!important +} + +.rgba-purple-slight { + background-color: rgba(156, 39, 176, .1)!important +} + +.rgba-indigo-slight { + background-color: rgba(63, 81, 181, .1)!important +} + +.rgba-cyan-slight { + background-color: rgba(0, 188, 212, .1)!important +} + +.rgba-teal-slight { + background-color: rgba(0, 150, 136, .1)!important +} + +.rgba-green-slight { + background-color: rgba(76, 175, 80, .1)!important +} + +.rgba-lime-slight { + background-color: rgba(205, 220, 57, .1)!important +} + +.rgba-yellow-slight { + background-color: rgba(255, 235, 59, .1)!important +} + +.rgba-orange-slight { + background-color: rgba(255, 152, 0, .1)!important +} + +.rgba-brown-slight { + background-color: rgba(121, 85, 72, .1)!important +} + +.rgba-grey-slight { + background-color: rgba(158, 158, 158, .1)!important +} + +.rgba-bluegrey-slight { + background-color: rgba(96, 125, 139, .1)!important +} + +.rgba-black-slight { + background-color: rgba(0, 0, 0, .1)!important +} + +.rgba-stylish-slight { + background-color: rgba(62, 69, 81, .1)!important +} + +.rgba-white-slight { + background-color: rgba(255, 255, 255, .1)!important +} + +.bg-primary { + background-color: #4285F4!important +} + +.bg-danger { + background-color: #ff3547!important +} + +.bg-warning { + background-color: #F80!important +} + +.bg-success { + background-color: #00C851!important +} + +.bg-info { + background-color: #33b5e5!important +} + +.bg-default { + background-color: #2BBBAD!important +} + +.bg-secondary { + background-color: #a6c!important +} + +.bg-elegant { + background-color: #2E2E2E!important +} + +.bg-unique { + background-color: #880e4f!important +} + +.bg-dark-green { + background-color: #388E3C!important +} + +.bg-mdb-color { + background-color: #59698D!important +} + +.bg-red { + background-color: #D32F2F!important +} + +.bg-pink { + background-color: #ec407a!important +} + +.bg-purple { + background-color: #8e24aa!important +} + +.bg-deep-purple { + background-color: #512da8!important +} + +.bg-indigo { + background-color: #3f51b5!important +} + +.bg-blue { + background-color: #1976D2!important +} + +.bg-light-blue { + background-color: #82B1FF!important +} + +.bg-cyan { + background-color: #00bcd4!important +} + +.bg-teal { + background-color: #00796b!important +} + +.bg-green { + background-color: #388E3C!important +} + +.bg-light-green { + background-color: #8bc34a!important +} + +.bg-lime { + background-color: #afb42b!important +} + +.bg-yellow { + background-color: #fbc02d!important +} + +.bg-amber { + background-color: #ffa000!important +} + +.bg-orange { + background-color: #f57c00!important +} + +.bg-deep-orange { + background-color: #ff7043!important +} + +.bg-brown { + background-color: #795548!important +} + +.bg-grey { + background-color: #616161!important +} + +.bg-blue-grey { + background-color: #78909c!important +} + +.bg-white { + background-color: #fff!important +} + +.bg-black { + background-color: #000!important +} + +.card.card-cascade.wider, +.colorful-select .dropdown-content li.disabled a:hover, +.colorful-select .dropdown-content li.disabled span:hover, +.colorful-select .dropdown-content li.disabled.active span, +.colorful-select .dropdown-content li.optgroup a:hover, +.colorful-select .dropdown-content li.optgroup span:hover, +.colorful-select .dropdown-content li.optgroup.active span, +.colorful-select .dropdown-content li:disabled a:hover, +.colorful-select .dropdown-content li:disabled span:hover, +.colorful-select .dropdown-content li:disabled.active span, +.modal-dialog.cascading-modal.modal-avatar .modal-header, +.z-depth-0 { + -webkit-box-shadow: none!important; + box-shadow: none!important +} + +#toast-container>div, +.author-box, +.badge, +.btn, +.btn-primary.active:not([disabled]):not(.disabled), +.btn-primary:not([disabled]):not(.disabled):active, +.card-wrapper .back, +.card-wrapper .front, +.card.card-cascade.wider .card-body, +.card:not([class*=card-outline-]), +.chip, +.counter, +.dropdown-content, +.jumbotron, +.md-pills .nav-link.active, +.modal-dialog.cascading-modal .modal-c-tabs .nav-tabs, +.modal-dialog.modal-notify .modal-header, +.navbar, +.pagination .active .page-link, +.pricing-card .price .version, +.section-blog-fw .view, +.show>.btn-primary.dropdown-toggle, +.side-nav, +.social-list, +.z-depth-1 { + -webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12); + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12) +} + +.btn-floating, +.btn-floating.btn-flat.active, +.btn:active, +.btn:focus, +.btn:hover, +.card.card-cascade.card-avatar img, +.card.card-cascade.wider.reverse .card-body, +.colorful-select .dropdown-content li.active span, +.comments-list .badge, +.dropdown .dropdown-menu .dropdown-item:active, +.dropdown .dropdown-menu .dropdown-item:hover, +.form-header, +.md-pills .nav-link.active:hover, +.media .media-left img, +.modal-dialog .modal-content, +.modal-dialog.cascading-modal .modal-header, +.nav-tabs, +.picker__box .picker__table .picker--focused, +.picker__box .picker__table .picker__day--selected, +.picker__box .picker__table .picker__day--selected:hover, +.pricing-card .header, +.reply-form .badge, +.z-depth-1-half, +ul.instagram-photos li img { + -webkit-box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15) +} + +.btn-floating:hover, +.card-overlay, +.card.card-cascade .view, +.colorful-select .dropdown-content li a:hover, +.colorful-select .dropdown-content li span:hover, +.comments-list img, +.modal-dialog.cascading-modal.modal-avatar .modal-header img, +.reply-form img, +.testimonial-carousel .testimonial .avatar img, +.z-depth-2 { + -webkit-box-shadow: 0 8px 17px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19); + box-shadow: 0 8px 17px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19) +} + +.z-depth-3 { + -webkit-box-shadow: 0 12px 15px 0 rgba(0, 0, 0, .24), 0 17px 50px 0 rgba(0, 0, 0, .19); + box-shadow: 0 12px 15px 0 rgba(0, 0, 0, .24), 0 17px 50px 0 rgba(0, 0, 0, .19) +} + +.z-depth-4 { + -webkit-box-shadow: 0 16px 28px 0 rgba(0, 0, 0, .22), 0 25px 55px 0 rgba(0, 0, 0, .21); + box-shadow: 0 16px 28px 0 rgba(0, 0, 0, .22), 0 25px 55px 0 rgba(0, 0, 0, .21) +} + +.z-depth-5 { + -webkit-box-shadow: 0 27px 24px 0 rgba(0, 0, 0, .2), 0 40px 77px 0 rgba(0, 0, 0, .22); + box-shadow: 0 27px 24px 0 rgba(0, 0, 0, .2), 0 40px 77px 0 rgba(0, 0, 0, .22) +} + +.hoverable { + -webkit-transition: box-shadow .55s; + -webkit-transition: -webkit-box-shadow .55s; + transition: -webkit-box-shadow .55s; + transition: box-shadow .55s; + transition: box-shadow .55s, -webkit-box-shadow .55s; + -webkit-box-shadow: 0; + box-shadow: 0 +} + +.hoverable:hover { + -webkit-transition: box-shadow .45s; + -webkit-transition: -webkit-box-shadow .45s; + transition: -webkit-box-shadow .45s; + transition: box-shadow .45s; + transition: box-shadow .45s, -webkit-box-shadow .45s; + -webkit-box-shadow: 0 8px 17px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19); + box-shadow: 0 8px 17px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19) +} + +a { + color: #0275d8; + text-decoration: none; + cursor: pointer +} + +a:focus, +a:hover { + text-decoration: none +} + +a:not([href]):not([tabindex]), +a:not([href]):not([tabindex]):focus, +a:not([href]):not([tabindex]):hover { + color: inherit; + text-decoration: none +} + +.disabled { + cursor: not-allowed!important +} + +.author-box, +.badge, +.jumbotron, +.list-group .list-group-item, +.navbar-toggler { + border-radius: 2px +} + +.card .card-circle ul, +.card-overlay ul, +.flex-center ul, +.section.team-section .avatar ul, +.testimonial-carousel .testimonial .avatar ul { + list-style-type: none; + padding: 0; + text-align: center +} + +.pr-0, +.px-0 { + padding-right: 0!important +} + +.pl-0, +.px-0 { + padding-left: 0!important +} + +.pt-0, +.py-0 { + padding-top: 0!important +} + +.pb-0, +.py-0 { + padding-bottom: 0!important +} + +.media .avatar-sm { + width: 56px; + border-radius: 50% +} + +.animated { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both +} + +.animated.infinite { + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite +} + +.animated.hinge { + -webkit-animation-duration: 2s; + animation-duration: 2s +} + +.animated.bounceIn, +.animated.bounceOut, +.animated.flipOutX, +.animated.flipOutY { + -webkit-animation-duration: .75s; + animation-duration: .75s +} + +@-webkit-keyframes bounce { + 20%, + 53%, + 80%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(.755, .05, .855, .06); + animation-timing-function: cubic-bezier(.755, .05, .855, .06); + -webkit-transform: translate3d(0, -30px, 0); + transform: translate3d(0, -30px, 0) + } + 70% { + -webkit-animation-timing-function: cubic-bezier(.755, .05, .855, .06); + animation-timing-function: cubic-bezier(.755, .05, .855, .06); + -webkit-transform: translate3d(0, -15px, 0); + transform: translate3d(0, -15px, 0) + } + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0) + } +} + +@keyframes bounce { + 20%, + 53%, + 80%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + 40%, + 43% { + -webkit-animation-timing-function: cubic-bezier(.755, .05, .855, .06); + animation-timing-function: cubic-bezier(.755, .05, .855, .06); + -webkit-transform: translate3d(0, -30px, 0); + transform: translate3d(0, -30px, 0) + } + 70% { + -webkit-animation-timing-function: cubic-bezier(.755, .05, .855, .06); + animation-timing-function: cubic-bezier(.755, .05, .855, .06); + -webkit-transform: translate3d(0, -15px, 0); + transform: translate3d(0, -15px, 0) + } + 90% { + -webkit-transform: translate3d(0, -4px, 0); + transform: translate3d(0, -4px, 0) + } +} + +.bounce { + -webkit-animation-name: bounce; + animation-name: bounce; + -webkit-transform-origin: center bottom; + -ms-transform-origin: center bottom; + transform-origin: center bottom +} + +@-webkit-keyframes flash { + 50%, + from, + to { + opacity: 1 + } + 25%, + 75% { + opacity: 0 + } +} + +@keyframes flash { + 50%, + from, + to { + opacity: 1 + } + 25%, + 75% { + opacity: 0 + } +} + +.flash { + -webkit-animation-name: flash; + animation-name: flash +} + +@-webkit-keyframes pulse { + from, + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05) + } +} + +@keyframes pulse { + from, + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } + 50% { + -webkit-transform: scale3d(1.05, 1.05, 1.05); + transform: scale3d(1.05, 1.05, 1.05) + } +} + +.pulse { + -webkit-animation-name: pulse; + animation-name: pulse +} + +@-webkit-keyframes rubberBand { + from, + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } + 30% { + -webkit-transform: scale3d(1.25, .75, 1); + transform: scale3d(1.25, .75, 1) + } + 40% { + -webkit-transform: scale3d(.75, 1.25, 1); + transform: scale3d(.75, 1.25, 1) + } + 50% { + -webkit-transform: scale3d(1.15, .85, 1); + transform: scale3d(1.15, .85, 1) + } + 65% { + -webkit-transform: scale3d(.95, 1.05, 1); + transform: scale3d(.95, 1.05, 1) + } + 75% { + -webkit-transform: scale3d(1.05, .95, 1); + transform: scale3d(1.05, .95, 1) + } +} + +@keyframes rubberBand { + from, + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } + 30% { + -webkit-transform: scale3d(1.25, .75, 1); + transform: scale3d(1.25, .75, 1) + } + 40% { + -webkit-transform: scale3d(.75, 1.25, 1); + transform: scale3d(.75, 1.25, 1) + } + 50% { + -webkit-transform: scale3d(1.15, .85, 1); + transform: scale3d(1.15, .85, 1) + } + 65% { + -webkit-transform: scale3d(.95, 1.05, 1); + transform: scale3d(.95, 1.05, 1) + } + 75% { + -webkit-transform: scale3d(1.05, .95, 1); + transform: scale3d(1.05, .95, 1) + } +} + +.rubberBand { + -webkit-animation-name: rubberBand; + animation-name: rubberBand +} + +@-webkit-keyframes shake { + from, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0) + } + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0) + } +} + +@keyframes shake { + from, + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + 10%, + 30%, + 50%, + 70%, + 90% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0) + } + 20%, + 40%, + 60%, + 80% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0) + } +} + +.shake { + -webkit-animation-name: shake; + animation-name: shake +} + +@-webkit-keyframes headShake { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0) + } + 6.5% { + -webkit-transform: translateX(-6px) rotateY(-9deg); + transform: translateX(-6px) rotateY(-9deg) + } + 18.5% { + -webkit-transform: translateX(5px) rotateY(7deg); + transform: translateX(5px) rotateY(7deg) + } + 31.5% { + -webkit-transform: translateX(-3px) rotateY(-5deg); + transform: translateX(-3px) rotateY(-5deg) + } + 43.5% { + -webkit-transform: translateX(2px) rotateY(3deg); + transform: translateX(2px) rotateY(3deg) + } + 50% { + -webkit-transform: translateX(0); + transform: translateX(0) + } +} + +@keyframes headShake { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0) + } + 6.5% { + -webkit-transform: translateX(-6px) rotateY(-9deg); + transform: translateX(-6px) rotateY(-9deg) + } + 18.5% { + -webkit-transform: translateX(5px) rotateY(7deg); + transform: translateX(5px) rotateY(7deg) + } + 31.5% { + -webkit-transform: translateX(-3px) rotateY(-5deg); + transform: translateX(-3px) rotateY(-5deg) + } + 43.5% { + -webkit-transform: translateX(2px) rotateY(3deg); + transform: translateX(2px) rotateY(3deg) + } + 50% { + -webkit-transform: translateX(0); + transform: translateX(0) + } +} + +.headShake { + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + -webkit-animation-name: headShake; + animation-name: headShake +} + +@-webkit-keyframes swing { + 20% { + -webkit-transform: rotate3d(0, 0, 1, 15deg); + transform: rotate3d(0, 0, 1, 15deg) + } + 40% { + -webkit-transform: rotate3d(0, 0, 1, -10deg); + transform: rotate3d(0, 0, 1, -10deg) + } + 60% { + -webkit-transform: rotate3d(0, 0, 1, 5deg); + transform: rotate3d(0, 0, 1, 5deg) + } + 80% { + -webkit-transform: rotate3d(0, 0, 1, -5deg); + transform: rotate3d(0, 0, 1, -5deg) + } + to { + -webkit-transform: rotate3d(0, 0, 1, 0deg); + transform: rotate3d(0, 0, 1, 0deg) + } +} + +@keyframes swing { + 20% { + -webkit-transform: rotate3d(0, 0, 1, 15deg); + transform: rotate3d(0, 0, 1, 15deg) + } + 40% { + -webkit-transform: rotate3d(0, 0, 1, -10deg); + transform: rotate3d(0, 0, 1, -10deg) + } + 60% { + -webkit-transform: rotate3d(0, 0, 1, 5deg); + transform: rotate3d(0, 0, 1, 5deg) + } + 80% { + -webkit-transform: rotate3d(0, 0, 1, -5deg); + transform: rotate3d(0, 0, 1, -5deg) + } + to { + -webkit-transform: rotate3d(0, 0, 1, 0deg); + transform: rotate3d(0, 0, 1, 0deg) + } +} + +.swing { + -webkit-transform-origin: top center; + -ms-transform-origin: top center; + transform-origin: top center; + -webkit-animation-name: swing; + animation-name: swing +} + +@-webkit-keyframes tada { + from, + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } + 10%, + 20% { + -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); + transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg) + } + 30%, + 50%, + 70%, + 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg) + } + 40%, + 60%, + 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg) + } +} + +@keyframes tada { + from, + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } + 10%, + 20% { + -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg); + transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg) + } + 30%, + 50%, + 70%, + 90% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg) + } + 40%, + 60%, + 80% { + -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg) + } +} + +.tada { + -webkit-animation-name: tada; + animation-name: tada +} + +@-webkit-keyframes wobble { + from, + to { + -webkit-transform: none; + transform: none + } + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg) + } + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg) + } + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg) + } + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg) + } + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg) + } +} + +@keyframes wobble { + from, + to { + -webkit-transform: none; + transform: none + } + 15% { + -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); + transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg) + } + 30% { + -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); + transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg) + } + 45% { + -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); + transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg) + } + 60% { + -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); + transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg) + } + 75% { + -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); + transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg) + } +} + +.wobble { + -webkit-animation-name: wobble; + animation-name: wobble +} + +@-webkit-keyframes jello { + 11.1%, + from, + to { + -webkit-transform: none; + transform: none + } + 22.2% { + -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); + transform: skewX(-12.5deg) skewY(-12.5deg) + } + 33.3% { + -webkit-transform: skewX(6.25deg) skewY(6.25deg); + transform: skewX(6.25deg) skewY(6.25deg) + } + 44.4% { + -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); + transform: skewX(-3.125deg) skewY(-3.125deg) + } + 55.5% { + -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); + transform: skewX(1.5625deg) skewY(1.5625deg) + } + 66.6% { + -webkit-transform: skewX(-.78125deg) skewY(-.78125deg); + transform: skewX(-.78125deg) skewY(-.78125deg) + } + 77.7% { + -webkit-transform: skewX(.39063deg) skewY(.39063deg); + transform: skewX(.39063deg) skewY(.39063deg) + } + 88.8% { + -webkit-transform: skewX(-.19531deg) skewY(-.19531deg); + transform: skewX(-.19531deg) skewY(-.19531deg) + } +} + +@keyframes jello { + 11.1%, + from, + to { + -webkit-transform: none; + transform: none + } + 22.2% { + -webkit-transform: skewX(-12.5deg) skewY(-12.5deg); + transform: skewX(-12.5deg) skewY(-12.5deg) + } + 33.3% { + -webkit-transform: skewX(6.25deg) skewY(6.25deg); + transform: skewX(6.25deg) skewY(6.25deg) + } + 44.4% { + -webkit-transform: skewX(-3.125deg) skewY(-3.125deg); + transform: skewX(-3.125deg) skewY(-3.125deg) + } + 55.5% { + -webkit-transform: skewX(1.5625deg) skewY(1.5625deg); + transform: skewX(1.5625deg) skewY(1.5625deg) + } + 66.6% { + -webkit-transform: skewX(-.78125deg) skewY(-.78125deg); + transform: skewX(-.78125deg) skewY(-.78125deg) + } + 77.7% { + -webkit-transform: skewX(.39063deg) skewY(.39063deg); + transform: skewX(.39063deg) skewY(.39063deg) + } + 88.8% { + -webkit-transform: skewX(-.19531deg) skewY(-.19531deg); + transform: skewX(-.19531deg) skewY(-.19531deg) + } +} + +.jello { + -webkit-animation-name: jello; + animation-name: jello; + -webkit-transform-origin: center; + -ms-transform-origin: center; + transform-origin: center +} + +@-webkit-keyframes bounceIn { + 20%, + 40%, + 60%, + 80%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3) + } + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1) + } + 40% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03) + } + 80% { + -webkit-transform: scale3d(.97, .97, .97); + transform: scale3d(.97, .97, .97) + } + to { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } +} + +@keyframes bounceIn { + 20%, + 40%, + 60%, + 80%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3) + } + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1) + } + 40% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03) + } + 80% { + -webkit-transform: scale3d(.97, .97, .97); + transform: scale3d(.97, .97, .97) + } + to { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } +} + +.bounceIn { + -webkit-animation-name: bounceIn; + animation-name: bounceIn +} + +@-webkit-keyframes bounceInDown { + 60%, + 75%, + 90%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0); + transform: translate3d(0, -3000px, 0) + } + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0) + } + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0) + } + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0) + } + to { + -webkit-transform: none; + transform: none + } +} + +@keyframes bounceInDown { + 60%, + 75%, + 90%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -3000px, 0); + transform: translate3d(0, -3000px, 0) + } + 60% { + opacity: 1; + -webkit-transform: translate3d(0, 25px, 0); + transform: translate3d(0, 25px, 0) + } + 75% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0) + } + 90% { + -webkit-transform: translate3d(0, 5px, 0); + transform: translate3d(0, 5px, 0) + } + to { + -webkit-transform: none; + transform: none + } +} + +.bounceInDown { + -webkit-animation-name: bounceInDown; + animation-name: bounceInDown +} + +@-webkit-keyframes bounceInLeft { + 60%, + 75%, + 90%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0); + transform: translate3d(-3000px, 0, 0) + } + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0) + } + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0) + } + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0) + } + to { + -webkit-transform: none; + transform: none + } +} + +@keyframes bounceInLeft { + 60%, + 75%, + 90%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + 0% { + opacity: 0; + -webkit-transform: translate3d(-3000px, 0, 0); + transform: translate3d(-3000px, 0, 0) + } + 60% { + opacity: 1; + -webkit-transform: translate3d(25px, 0, 0); + transform: translate3d(25px, 0, 0) + } + 75% { + -webkit-transform: translate3d(-10px, 0, 0); + transform: translate3d(-10px, 0, 0) + } + 90% { + -webkit-transform: translate3d(5px, 0, 0); + transform: translate3d(5px, 0, 0) + } + to { + -webkit-transform: none; + transform: none + } +} + +.bounceInLeft { + -webkit-animation-name: bounceInLeft; + animation-name: bounceInLeft +} + +@-webkit-keyframes bounceInRight { + 60%, + 75%, + 90%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + from { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0); + transform: translate3d(3000px, 0, 0) + } + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0) + } + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0) + } + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0) + } + to { + -webkit-transform: none; + transform: none + } +} + +@keyframes bounceInRight { + 60%, + 75%, + 90%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + from { + opacity: 0; + -webkit-transform: translate3d(3000px, 0, 0); + transform: translate3d(3000px, 0, 0) + } + 60% { + opacity: 1; + -webkit-transform: translate3d(-25px, 0, 0); + transform: translate3d(-25px, 0, 0) + } + 75% { + -webkit-transform: translate3d(10px, 0, 0); + transform: translate3d(10px, 0, 0) + } + 90% { + -webkit-transform: translate3d(-5px, 0, 0); + transform: translate3d(-5px, 0, 0) + } + to { + -webkit-transform: none; + transform: none + } +} + +.bounceInRight { + -webkit-animation-name: bounceInRight; + animation-name: bounceInRight +} + +@-webkit-keyframes bounceInUp { + 60%, + 75%, + 90%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + from { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0); + transform: translate3d(0, 3000px, 0) + } + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0) + } + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0) + } + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0) + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +@keyframes bounceInUp { + 60%, + 75%, + 90%, + from, + to { + -webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1); + animation-timing-function: cubic-bezier(.215, .61, .355, 1) + } + from { + opacity: 0; + -webkit-transform: translate3d(0, 3000px, 0); + transform: translate3d(0, 3000px, 0) + } + 60% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0) + } + 75% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0) + } + 90% { + -webkit-transform: translate3d(0, -5px, 0); + transform: translate3d(0, -5px, 0) + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +.bounceInUp { + -webkit-animation-name: bounceInUp; + animation-name: bounceInUp +} + +@-webkit-keyframes bounceOut { + 20% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9) + } + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1) + } + to { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3) + } +} + +@keyframes bounceOut { + 20% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9) + } + 50%, + 55% { + opacity: 1; + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1) + } + to { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3) + } +} + +.bounceOut { + -webkit-animation-name: bounceOut; + animation-name: bounceOut +} + +@-webkit-keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0) + } + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0) + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0) + } +} + +@keyframes bounceOutDown { + 20% { + -webkit-transform: translate3d(0, 10px, 0); + transform: translate3d(0, 10px, 0) + } + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0) + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0) + } +} + +.bounceOutDown { + -webkit-animation-name: bounceOutDown; + animation-name: bounceOutDown +} + +@-webkit-keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0) + } + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0) + } +} + +@keyframes bounceOutLeft { + 20% { + opacity: 1; + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0) + } + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0) + } +} + +.bounceOutLeft { + -webkit-animation-name: bounceOutLeft; + animation-name: bounceOutLeft +} + +@-webkit-keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0) + } + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0) + } +} + +@keyframes bounceOutRight { + 20% { + opacity: 1; + -webkit-transform: translate3d(-20px, 0, 0); + transform: translate3d(-20px, 0, 0) + } + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0) + } +} + +.bounceOutRight { + -webkit-animation-name: bounceOutRight; + animation-name: bounceOutRight +} + +@-webkit-keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0) + } + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0) + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0) + } +} + +@keyframes bounceOutUp { + 20% { + -webkit-transform: translate3d(0, -10px, 0); + transform: translate3d(0, -10px, 0) + } + 40%, + 45% { + opacity: 1; + -webkit-transform: translate3d(0, 20px, 0); + transform: translate3d(0, 20px, 0) + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0) + } +} + +.bounceOutUp { + -webkit-animation-name: bounceOutUp; + animation-name: bounceOutUp +} + +@-webkit-keyframes fadeIn { + from { + opacity: 0 + } + to { + opacity: 1 + } +} + +@keyframes fadeIn { + from { + opacity: 0 + } + to { + opacity: 1 + } +} + +.fadeIn { + -webkit-animation-name: fadeIn; + animation-name: fadeIn +} + +@-webkit-keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown +} + +@-webkit-keyframes fadeInDownBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes fadeInDownBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.fadeInDownBig { + -webkit-animation-name: fadeInDownBig; + animation-name: fadeInDownBig +} + +@-webkit-keyframes fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes fadeInLeft { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.fadeInLeft { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft +} + +@-webkit-keyframes fadeInLeftBig { + from { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes fadeInLeftBig { + from { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.fadeInLeftBig { + -webkit-animation-name: fadeInLeftBig; + animation-name: fadeInLeftBig +} + +@-webkit-keyframes fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes fadeInRight { + from { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.fadeInRight { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight +} + +@-webkit-keyframes fadeInRightBig { + from { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes fadeInRightBig { + from { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.fadeInRightBig { + -webkit-animation-name: fadeInRightBig; + animation-name: fadeInRightBig +} + +@-webkit-keyframes fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes fadeInUp { + from { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.fadeInUp { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp +} + +@-webkit-keyframes fadeInUpBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes fadeInUpBig { + from { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.fadeInUpBig { + -webkit-animation-name: fadeInUpBig; + animation-name: fadeInUpBig +} + +@-webkit-keyframes fadeOut { + from { + opacity: 1 + } + to { + opacity: 0 + } +} + +@keyframes fadeOut { + from { + opacity: 1 + } + to { + opacity: 0 + } +} + +.fadeOut { + -webkit-animation-name: fadeOut; + animation-name: fadeOut +} + +@-webkit-keyframes fadeOutDown { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) + } +} + +@keyframes fadeOutDown { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) + } +} + +.fadeOutDown { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown +} + +@-webkit-keyframes fadeOutDownBig { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0) + } +} + +@keyframes fadeOutDownBig { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0) + } +} + +.fadeOutDownBig { + -webkit-animation-name: fadeOutDownBig; + animation-name: fadeOutDownBig +} + +@-webkit-keyframes fadeOutLeft { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } +} + +@keyframes fadeOutLeft { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } +} + +.fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft +} + +@-webkit-keyframes fadeOutLeftBig { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0) + } +} + +@keyframes fadeOutLeftBig { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(-2000px, 0, 0); + transform: translate3d(-2000px, 0, 0) + } +} + +.fadeOutLeftBig { + -webkit-animation-name: fadeOutLeftBig; + animation-name: fadeOutLeftBig +} + +@-webkit-keyframes fadeOutRight { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } +} + +@keyframes fadeOutRight { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } +} + +.fadeOutRight { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight +} + +@-webkit-keyframes fadeOutRightBig { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0) + } +} + +@keyframes fadeOutRightBig { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(2000px, 0, 0); + transform: translate3d(2000px, 0, 0) + } +} + +.fadeOutRightBig { + -webkit-animation-name: fadeOutRightBig; + animation-name: fadeOutRightBig +} + +@-webkit-keyframes fadeOutUp { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) + } +} + +@keyframes fadeOutUp { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) + } +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp +} + +@-webkit-keyframes fadeOutUpBig { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0) + } +} + +@keyframes fadeOutUpBig { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -2000px, 0); + transform: translate3d(0, -2000px, 0) + } +} + +.fadeOutUpBig { + -webkit-animation-name: fadeOutUpBig; + animation-name: fadeOutUpBig +} + +@-webkit-keyframes flip { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out + } + 40% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out + } + 50% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } + 80% { + -webkit-transform: perspective(400px) scale3d(.95, .95, .95); + transform: perspective(400px) scale3d(.95, .95, .95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } +} + +@keyframes flip { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + transform: perspective(400px) rotate3d(0, 1, 0, -360deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out + } + 40% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out + } + 50% { + -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } + 80% { + -webkit-transform: perspective(400px) scale3d(.95, .95, .95); + transform: perspective(400px) scale3d(.95, .95, .95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } +} + +.animated.flip { + -webkit-backface-visibility: visible; + backface-visibility: visible; + -webkit-animation-name: flip; + animation-name: flip +} + +@-webkit-keyframes flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0 + } + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1 + } + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg) + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px) + } +} + +@keyframes flipInX { + from { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0 + } + 40% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } + 60% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + transform: perspective(400px) rotate3d(1, 0, 0, 10deg); + opacity: 1 + } + 80% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); + transform: perspective(400px) rotate3d(1, 0, 0, -5deg) + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px) + } +} + +.flipInX { + -webkit-backface-visibility: visible!important; + backface-visibility: visible!important; + -webkit-animation-name: flipInX; + animation-name: flipInX +} + +.flipInY, +.flipOutX { + -webkit-backface-visibility: visible!important +} + +@-webkit-keyframes flipInY { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0 + } + 40% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } + 60% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + opacity: 1 + } + 80% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + transform: perspective(400px) rotate3d(0, 1, 0, -5deg) + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px) + } +} + +@keyframes flipInY { + from { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + opacity: 0 + } + 40% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + transform: perspective(400px) rotate3d(0, 1, 0, -20deg); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in + } + 60% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + transform: perspective(400px) rotate3d(0, 1, 0, 10deg); + opacity: 1 + } + 80% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg); + transform: perspective(400px) rotate3d(0, 1, 0, -5deg) + } + to { + -webkit-transform: perspective(400px); + transform: perspective(400px) + } +} + +.flipInY { + backface-visibility: visible!important; + -webkit-animation-name: flipInY; + animation-name: flipInY +} + +@-webkit-keyframes flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px) + } + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1 + } + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0 + } +} + +@keyframes flipOutX { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px) + } + 30% { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + transform: perspective(400px) rotate3d(1, 0, 0, -20deg); + opacity: 1 + } + to { + -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + transform: perspective(400px) rotate3d(1, 0, 0, 90deg); + opacity: 0 + } +} + +.flipOutX { + -webkit-animation-name: flipOutX; + animation-name: flipOutX; + backface-visibility: visible!important +} + +@-webkit-keyframes flipOutY { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px) + } + 30% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + opacity: 1 + } + to { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + opacity: 0 + } +} + +@keyframes flipOutY { + from { + -webkit-transform: perspective(400px); + transform: perspective(400px) + } + 30% { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + transform: perspective(400px) rotate3d(0, 1, 0, -15deg); + opacity: 1 + } + to { + -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + transform: perspective(400px) rotate3d(0, 1, 0, 90deg); + opacity: 0 + } +} + +.flipOutY { + -webkit-backface-visibility: visible!important; + backface-visibility: visible!important; + -webkit-animation-name: flipOutY; + animation-name: flipOutY +} + +@-webkit-keyframes lightSpeedIn { + from { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0 + } + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1 + } + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + opacity: 1 + } + to { + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +@keyframes lightSpeedIn { + from { + -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg); + transform: translate3d(100%, 0, 0) skewX(-30deg); + opacity: 0 + } + 60% { + -webkit-transform: skewX(20deg); + transform: skewX(20deg); + opacity: 1 + } + 80% { + -webkit-transform: skewX(-5deg); + transform: skewX(-5deg); + opacity: 1 + } + to { + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +.lightSpeedIn { + -webkit-animation-name: lightSpeedIn; + animation-name: lightSpeedIn; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out +} + +@-webkit-keyframes lightSpeedOut { + from { + opacity: 1 + } + to { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0 + } +} + +@keyframes lightSpeedOut { + from { + opacity: 1 + } + to { + -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); + transform: translate3d(100%, 0, 0) skewX(30deg); + opacity: 0 + } +} + +.lightSpeedOut { + -webkit-animation-name: lightSpeedOut; + animation-name: lightSpeedOut; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in +} + +@-webkit-keyframes rotateIn { + from { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, -200deg); + transform: rotate3d(0, 0, 1, -200deg); + opacity: 0 + } + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +@keyframes rotateIn { + from { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, -200deg); + transform: rotate3d(0, 0, 1, -200deg); + opacity: 0 + } + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +.rotateIn { + -webkit-animation-name: rotateIn; + animation-name: rotateIn +} + +@-webkit-keyframes rotateInDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0 + } + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +@keyframes rotateInDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0 + } + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +.rotateInDownLeft { + -webkit-animation-name: rotateInDownLeft; + animation-name: rotateInDownLeft +} + +@-webkit-keyframes rotateInDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0 + } + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +@keyframes rotateInDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0 + } + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +.rotateInDownRight { + -webkit-animation-name: rotateInDownRight; + animation-name: rotateInDownRight +} + +@-webkit-keyframes rotateInUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0 + } + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +@keyframes rotateInUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0 + } + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +.rotateInUpLeft { + -webkit-animation-name: rotateInUpLeft; + animation-name: rotateInUpLeft +} + +@-webkit-keyframes rotateInUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -90deg); + transform: rotate3d(0, 0, 1, -90deg); + opacity: 0 + } + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +@keyframes rotateInUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -90deg); + transform: rotate3d(0, 0, 1, -90deg); + opacity: 0 + } + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: none; + transform: none; + opacity: 1 + } +} + +.rotateInUpRight { + -webkit-animation-name: rotateInUpRight; + animation-name: rotateInUpRight +} + +@-webkit-keyframes rotateOut { + from { + -webkit-transform-origin: center; + transform-origin: center; + opacity: 1 + } + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, 200deg); + transform: rotate3d(0, 0, 1, 200deg); + opacity: 0 + } +} + +@keyframes rotateOut { + from { + -webkit-transform-origin: center; + transform-origin: center; + opacity: 1 + } + to { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-transform: rotate3d(0, 0, 1, 200deg); + transform: rotate3d(0, 0, 1, 200deg); + opacity: 0 + } +} + +.rotateOut { + -webkit-animation-name: rotateOut; + animation-name: rotateOut +} + +@-webkit-keyframes rotateOutDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1 + } + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0 + } +} + +@keyframes rotateOutDownLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1 + } + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, 45deg); + transform: rotate3d(0, 0, 1, 45deg); + opacity: 0 + } +} + +.rotateOutDownLeft { + -webkit-animation-name: rotateOutDownLeft; + animation-name: rotateOutDownLeft +} + +@-webkit-keyframes rotateOutDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1 + } + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0 + } +} + +@keyframes rotateOutDownRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1 + } + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0 + } +} + +.rotateOutDownRight { + -webkit-animation-name: rotateOutDownRight; + animation-name: rotateOutDownRight +} + +@-webkit-keyframes rotateOutUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1 + } + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0 + } +} + +@keyframes rotateOutUpLeft { + from { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + opacity: 1 + } + to { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate3d(0, 0, 1, -45deg); + transform: rotate3d(0, 0, 1, -45deg); + opacity: 0 + } +} + +.rotateOutUpLeft { + -webkit-animation-name: rotateOutUpLeft; + animation-name: rotateOutUpLeft +} + +@-webkit-keyframes rotateOutUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1 + } + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 90deg); + transform: rotate3d(0, 0, 1, 90deg); + opacity: 0 + } +} + +@keyframes rotateOutUpRight { + from { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + opacity: 1 + } + to { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate3d(0, 0, 1, 90deg); + transform: rotate3d(0, 0, 1, 90deg); + opacity: 0 + } +} + +.rotateOutUpRight { + -webkit-animation-name: rotateOutUpRight; + animation-name: rotateOutUpRight +} + +@-webkit-keyframes hinge { + 0% { + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out + } + 20%, + 60% { + -webkit-transform: rotate3d(0, 0, 1, 80deg); + transform: rotate3d(0, 0, 1, 80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out + } + 40%, + 80% { + -webkit-transform: rotate3d(0, 0, 1, 60deg); + transform: rotate3d(0, 0, 1, 60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1 + } + to { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0 + } +} + +@keyframes hinge { + 0% { + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out + } + 20%, + 60% { + -webkit-transform: rotate3d(0, 0, 1, 80deg); + transform: rotate3d(0, 0, 1, 80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out + } + 40%, + 80% { + -webkit-transform: rotate3d(0, 0, 1, 60deg); + transform: rotate3d(0, 0, 1, 60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1 + } + to { + -webkit-transform: translate3d(0, 700px, 0); + transform: translate3d(0, 700px, 0); + opacity: 0 + } +} + +.hinge { + -webkit-animation-name: hinge; + animation-name: hinge +} + +@-webkit-keyframes rollIn { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +@keyframes rollIn { + from { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg); + transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg) + } + to { + opacity: 1; + -webkit-transform: none; + transform: none + } +} + +.rollIn { + -webkit-animation-name: rollIn; + animation-name: rollIn +} + +@-webkit-keyframes rollOut { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg) + } +} + +@keyframes rollOut { + from { + opacity: 1 + } + to { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg); + transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg) + } +} + +.rollOut { + -webkit-animation-name: rollOut; + animation-name: rollOut +} + +@-webkit-keyframes zoomIn { + from { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3) + } + 50% { + opacity: 1 + } +} + +@keyframes zoomIn { + from { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3) + } + 50% { + opacity: 1 + } +} + +.zoomIn { + -webkit-animation-name: zoomIn; + animation-name: zoomIn +} + +@-webkit-keyframes zoomInDown { + from { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +@keyframes zoomInDown { + from { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +.zoomInDown { + -webkit-animation-name: zoomInDown; + animation-name: zoomInDown +} + +@-webkit-keyframes zoomInLeft { + from { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); + transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +@keyframes zoomInLeft { + from { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); + transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +.zoomInLeft { + -webkit-animation-name: zoomInLeft; + animation-name: zoomInLeft +} + +@-webkit-keyframes zoomInRight { + from { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); + transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +@keyframes zoomInRight { + from { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); + transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +.zoomInRight { + -webkit-animation-name: zoomInRight; + animation-name: zoomInRight +} + +@-webkit-keyframes zoomInUp { + from { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +@keyframes zoomInUp { + from { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + 60% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +.zoomInUp { + -webkit-animation-name: zoomInUp; + animation-name: zoomInUp +} + +@-webkit-keyframes zoomOut { + from { + opacity: 1 + } + 50% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3) + } + to { + opacity: 0 + } +} + +@keyframes zoomOut { + from { + opacity: 1 + } + 50% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3) + } + to { + opacity: 0 + } +} + +.zoomOut { + -webkit-animation-name: zoomOut; + animation-name: zoomOut +} + +@-webkit-keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + to { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +@keyframes zoomOutDown { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + to { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +.zoomOutDown { + -webkit-animation-name: zoomOutDown; + animation-name: zoomOutDown +} + +@-webkit-keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0) + } + to { + opacity: 0; + -webkit-transform: scale(.1) translate3d(-2000px, 0, 0); + transform: scale(.1) translate3d(-2000px, 0, 0); + -webkit-transform-origin: left center; + transform-origin: left center + } +} + +@keyframes zoomOutLeft { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0) + } + to { + opacity: 0; + -webkit-transform: scale(.1) translate3d(-2000px, 0, 0); + transform: scale(.1) translate3d(-2000px, 0, 0); + -webkit-transform-origin: left center; + transform-origin: left center + } +} + +.zoomOutLeft { + -webkit-animation-name: zoomOutLeft; + animation-name: zoomOutLeft +} + +@-webkit-keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0) + } + to { + opacity: 0; + -webkit-transform: scale(.1) translate3d(2000px, 0, 0); + transform: scale(.1) translate3d(2000px, 0, 0); + -webkit-transform-origin: right center; + transform-origin: right center + } +} + +@keyframes zoomOutRight { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0); + transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0) + } + to { + opacity: 0; + -webkit-transform: scale(.1) translate3d(2000px, 0, 0); + transform: scale(.1) translate3d(2000px, 0, 0); + -webkit-transform-origin: right center; + transform-origin: right center + } +} + +.zoomOutRight { + -webkit-animation-name: zoomOutRight; + animation-name: zoomOutRight +} + +@-webkit-keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + to { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +@keyframes zoomOutUp { + 40% { + opacity: 1; + -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0); + -webkit-animation-timing-function: cubic-bezier(.55, .055, .675, .19); + animation-timing-function: cubic-bezier(.55, .055, .675, .19) + } + to { + opacity: 0; + -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); + transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0); + -webkit-transform-origin: center bottom; + transform-origin: center bottom; + -webkit-animation-timing-function: cubic-bezier(.175, .885, .32, 1); + animation-timing-function: cubic-bezier(.175, .885, .32, 1) + } +} + +.zoomOutUp { + -webkit-animation-name: zoomOutUp; + animation-name: zoomOutUp +} + +@-webkit-keyframes slideInDown { + from { + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + visibility: visible + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +@keyframes slideInDown { + from { + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + visibility: visible + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +.slideInDown { + -webkit-animation-name: slideInDown; + animation-name: slideInDown +} + +@-webkit-keyframes slideInLeft { + from { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + visibility: visible + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +@keyframes slideInLeft { + from { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + visibility: visible + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +.slideInLeft { + -webkit-animation-name: slideInLeft; + animation-name: slideInLeft +} + +@-webkit-keyframes slideInRight { + from { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + visibility: visible + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +@keyframes slideInRight { + from { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + visibility: visible + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +.slideInRight { + -webkit-animation-name: slideInRight; + animation-name: slideInRight +} + +@-webkit-keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +@keyframes slideInUp { + from { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + visibility: visible + } + to { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +.slideInUp { + -webkit-animation-name: slideInUp; + animation-name: slideInUp +} + +@-webkit-keyframes slideOutDown { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + to { + visibility: hidden; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) + } +} + +@keyframes slideOutDown { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + to { + visibility: hidden; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0) + } +} + +.slideOutDown { + -webkit-animation-name: slideOutDown; + animation-name: slideOutDown +} + +@-webkit-keyframes slideOutLeft { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + to { + visibility: hidden; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } +} + +@keyframes slideOutLeft { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + to { + visibility: hidden; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) + } +} + +.slideOutLeft { + -webkit-animation-name: slideOutLeft; + animation-name: slideOutLeft +} + +@-webkit-keyframes slideOutRight { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + to { + visibility: hidden; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } +} + +@keyframes slideOutRight { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + to { + visibility: hidden; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) + } +} + +.slideOutRight { + -webkit-animation-name: slideOutRight; + animation-name: slideOutRight +} + +@-webkit-keyframes slideOutUp { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + to { + visibility: hidden; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) + } +} + +@keyframes slideOutUp { + from { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } + to { + visibility: hidden; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0) + } +} + +.slideOutUp { + -webkit-animation-name: slideOutUp; + animation-name: slideOutUp +} + +.m-0 { + margin: 0!important +} + +.mr-1, +.mx-1 { + margin-right: .25rem!important +} + +.ml-1, +.mx-1 { + margin-left: .25rem!important +} + +.mt-1, +.my-1 { + margin-top: .25rem!important +} + +.mb-1, +.my-1 { + margin-bottom: .25rem!important +} + +.m-1, +.section-blog-fw .author-box, +.section-blog-fw .jumbotron { + margin: .25rem!important +} + +.mr-2, +.mx-2 { + margin-right: .5rem!important +} + +.ml-2, +.mx-2 { + margin-left: .5rem!important +} + +.mt-2, +.my-2 { + margin-top: .5rem!important +} + +.mb-2, +.my-2 { + margin-bottom: .5rem!important +} + +.m-2 { + margin: .5rem!important +} + +.mr-3, +.mx-3 { + margin-right: 1rem!important +} + +.ml-3, +.mx-3 { + margin-left: 1rem!important +} + +.mt-3, +.my-3 { + margin-top: 1rem!important +} + +.mb-3, +.my-3 { + margin-bottom: 1rem!important +} + +.m-3 { + margin: 1rem!important +} + +.mr-4, +.mx-4 { + margin-right: 1.5rem!important +} + +.ml-4, +.mx-4 { + margin-left: 1.5rem!important +} + +.mt-4, +.my-4 { + margin-top: 1.5rem!important +} + +.mb-4, +.my-4 { + margin-bottom: 1.5rem!important +} + +.m-4 { + margin: 1.5rem!important +} + +.mr-5, +.mx-5 { + margin-right: 3rem!important +} + +.ml-5, +.mx-5 { + margin-left: 3rem!important +} + +.mt-5, +.my-5 { + margin-top: 3rem!important +} + +.mb-5, +.my-5 { + margin-bottom: 3rem!important +} + +.m-5 { + margin: 3rem!important +} + +.mr-auto, +.mx-auto { + margin-right: auto!important +} + +.ml-auto, +.mx-auto { + margin-left: auto!important +} + +.mt-auto, +.my-auto { + margin-top: auto!important +} + +.mb-auto, +.my-auto { + margin-bottom: auto!important +} + +.p-0 { + padding: 0!important +} + +.pr-1, +.px-1 { + padding-right: .25rem!important +} + +.pl-1, +.px-1 { + padding-left: .25rem!important +} + +.pt-1, +.py-1 { + padding-top: .25rem!important +} + +.pb-1, +.py-1 { + padding-bottom: .25rem!important +} + +.p-1 { + padding: .25rem!important +} + +.pr-2, +.px-2 { + padding-right: .5rem!important +} + +.pl-2, +.px-2 { + padding-left: .5rem!important +} + +.pt-2, +.py-2 { + padding-top: .5rem!important +} + +.pb-2, +.py-2 { + padding-bottom: .5rem!important +} + +.p-2 { + padding: .5rem!important +} + +.pr-3, +.px-3 { + padding-right: 1rem!important +} + +.pl-3, +.px-3 { + padding-left: 1rem!important +} + +.pt-3, +.py-3 { + padding-top: 1rem!important +} + +.pb-3, +.py-3 { + padding-bottom: 1rem!important +} + +.p-3 { + padding: 1rem!important +} + +.pr-4, +.px-4 { + padding-right: 1.5rem!important +} + +.pl-4, +.px-4 { + padding-left: 1.5rem!important +} + +.pt-4, +.py-4 { + padding-top: 1.5rem!important +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem!important +} + +.p-4 { + padding: 1.5rem!important +} + +.pr-5, +.px-5 { + padding-right: 3rem!important +} + +.pl-5, +.px-5 { + padding-left: 3rem!important +} + +.pt-5, +.py-5 { + padding-top: 3rem!important +} + +.pb-5, +.py-5 { + padding-bottom: 3rem!important +} + +.p-5 { + padding: 3rem!important +} + +.m-auto { + margin: auto!important +} + +@media (min-width: 576px) { + .mr-sm-0, + .mx-sm-0 { + margin-right: 0!important + } + .ml-sm-0, + .mx-sm-0 { + margin-left: 0!important + } + .mt-sm-0, + .my-sm-0 { + margin-top: 0!important + } + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0!important + } + .pr-sm-0, + .px-sm-0 { + padding-right: 0!important + } + .pl-sm-0, + .px-sm-0 { + padding-left: 0!important + } + .pt-sm-0, + .py-sm-0 { + padding-top: 0!important + } + .pb-sm-0, + .py-sm-0 { + padding-bottom: 0!important + } + .m-sm-0 { + margin: 0!important + } + .mr-sm-1, + .mx-sm-1 { + margin-right: .25rem!important + } + .ml-sm-1, + .mx-sm-1 { + margin-left: .25rem!important + } + .mt-sm-1, + .my-sm-1 { + margin-top: .25rem!important + } + .mb-sm-1, + .my-sm-1 { + margin-bottom: .25rem!important + } + .m-sm-1 { + margin: .25rem!important + } + .mr-sm-2, + .mx-sm-2 { + margin-right: .5rem!important + } + .ml-sm-2, + .mx-sm-2 { + margin-left: .5rem!important + } + .mt-sm-2, + .my-sm-2 { + margin-top: .5rem!important + } + .mb-sm-2, + .my-sm-2 { + margin-bottom: .5rem!important + } + .m-sm-2 { + margin: .5rem!important + } + .mr-sm-3, + .mx-sm-3 { + margin-right: 1rem!important + } + .ml-sm-3, + .mx-sm-3 { + margin-left: 1rem!important + } + .mt-sm-3, + .my-sm-3 { + margin-top: 1rem!important + } + .mb-sm-3, + .my-sm-3 { + margin-bottom: 1rem!important + } + .m-sm-3 { + margin: 1rem!important + } + .mr-sm-4, + .mx-sm-4 { + margin-right: 1.5rem!important + } + .ml-sm-4, + .mx-sm-4 { + margin-left: 1.5rem!important + } + .mt-sm-4, + .my-sm-4 { + margin-top: 1.5rem!important + } + .mb-sm-4, + .my-sm-4 { + margin-bottom: 1.5rem!important + } + .m-sm-4 { + margin: 1.5rem!important + } + .mr-sm-5, + .mx-sm-5 { + margin-right: 3rem!important + } + .ml-sm-5, + .mx-sm-5 { + margin-left: 3rem!important + } + .mt-sm-5, + .my-sm-5 { + margin-top: 3rem!important + } + .mb-sm-5, + .my-sm-5 { + margin-bottom: 3rem!important + } + .m-sm-5 { + margin: 3rem!important + } + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto!important + } + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto!important + } + .mt-sm-auto, + .my-sm-auto { + margin-top: auto!important + } + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto!important + } + .p-sm-0 { + padding: 0!important + } + .pr-sm-1, + .px-sm-1 { + padding-right: .25rem!important + } + .pl-sm-1, + .px-sm-1 { + padding-left: .25rem!important + } + .pt-sm-1, + .py-sm-1 { + padding-top: .25rem!important + } + .pb-sm-1, + .py-sm-1 { + padding-bottom: .25rem!important + } + .p-sm-1 { + padding: .25rem!important + } + .pr-sm-2, + .px-sm-2 { + padding-right: .5rem!important + } + .pl-sm-2, + .px-sm-2 { + padding-left: .5rem!important + } + .pt-sm-2, + .py-sm-2 { + padding-top: .5rem!important + } + .pb-sm-2, + .py-sm-2 { + padding-bottom: .5rem!important + } + .p-sm-2 { + padding: .5rem!important + } + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem!important + } + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem!important + } + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem!important + } + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem!important + } + .p-sm-3 { + padding: 1rem!important + } + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem!important + } + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem!important + } + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem!important + } + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem!important + } + .p-sm-4 { + padding: 1.5rem!important + } + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem!important + } + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem!important + } + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem!important + } + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem!important + } + .p-sm-5 { + padding: 3rem!important + } + .m-sm-auto { + margin: auto!important + } +} + +@media (min-width: 768px) { + .mr-md-0, + .mx-md-0 { + margin-right: 0!important + } + .ml-md-0, + .mx-md-0 { + margin-left: 0!important + } + .mt-md-0, + .my-md-0 { + margin-top: 0!important + } + .mb-md-0, + .my-md-0 { + margin-bottom: 0!important + } + .pr-md-0, + .px-md-0 { + padding-right: 0!important + } + .pl-md-0, + .px-md-0 { + padding-left: 0!important + } + .pt-md-0, + .py-md-0 { + padding-top: 0!important + } + .pb-md-0, + .py-md-0 { + padding-bottom: 0!important + } + .m-md-0 { + margin: 0!important + } + .mr-md-1, + .mx-md-1 { + margin-right: .25rem!important + } + .ml-md-1, + .mx-md-1 { + margin-left: .25rem!important + } + .mt-md-1, + .my-md-1 { + margin-top: .25rem!important + } + .mb-md-1, + .my-md-1 { + margin-bottom: .25rem!important + } + .m-md-1 { + margin: .25rem!important + } + .mr-md-2, + .mx-md-2 { + margin-right: .5rem!important + } + .ml-md-2, + .mx-md-2 { + margin-left: .5rem!important + } + .mt-md-2, + .my-md-2 { + margin-top: .5rem!important + } + .mb-md-2, + .my-md-2 { + margin-bottom: .5rem!important + } + .m-md-2 { + margin: .5rem!important + } + .mr-md-3, + .mx-md-3 { + margin-right: 1rem!important + } + .ml-md-3, + .mx-md-3 { + margin-left: 1rem!important + } + .mt-md-3, + .my-md-3 { + margin-top: 1rem!important + } + .mb-md-3, + .my-md-3 { + margin-bottom: 1rem!important + } + .m-md-3 { + margin: 1rem!important + } + .mr-md-4, + .mx-md-4 { + margin-right: 1.5rem!important + } + .ml-md-4, + .mx-md-4 { + margin-left: 1.5rem!important + } + .mt-md-4, + .my-md-4 { + margin-top: 1.5rem!important + } + .mb-md-4, + .my-md-4 { + margin-bottom: 1.5rem!important + } + .m-md-4 { + margin: 1.5rem!important + } + .mr-md-5, + .mx-md-5 { + margin-right: 3rem!important + } + .ml-md-5, + .mx-md-5 { + margin-left: 3rem!important + } + .mt-md-5, + .my-md-5 { + margin-top: 3rem!important + } + .mb-md-5, + .my-md-5 { + margin-bottom: 3rem!important + } + .m-md-5 { + margin: 3rem!important + } + .mr-md-auto, + .mx-md-auto { + margin-right: auto!important + } + .ml-md-auto, + .mx-md-auto { + margin-left: auto!important + } + .mt-md-auto, + .my-md-auto { + margin-top: auto!important + } + .mb-md-auto, + .my-md-auto { + margin-bottom: auto!important + } + .p-md-0 { + padding: 0!important + } + .pr-md-1, + .px-md-1 { + padding-right: .25rem!important + } + .pl-md-1, + .px-md-1 { + padding-left: .25rem!important + } + .pt-md-1, + .py-md-1 { + padding-top: .25rem!important + } + .pb-md-1, + .py-md-1 { + padding-bottom: .25rem!important + } + .p-md-1 { + padding: .25rem!important + } + .pr-md-2, + .px-md-2 { + padding-right: .5rem!important + } + .pl-md-2, + .px-md-2 { + padding-left: .5rem!important + } + .pt-md-2, + .py-md-2 { + padding-top: .5rem!important + } + .pb-md-2, + .py-md-2 { + padding-bottom: .5rem!important + } + .p-md-2 { + padding: .5rem!important + } + .pr-md-3, + .px-md-3 { + padding-right: 1rem!important + } + .pl-md-3, + .px-md-3 { + padding-left: 1rem!important + } + .pt-md-3, + .py-md-3 { + padding-top: 1rem!important + } + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem!important + } + .p-md-3 { + padding: 1rem!important + } + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem!important + } + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem!important + } + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem!important + } + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem!important + } + .p-md-4 { + padding: 1.5rem!important + } + .pr-md-5, + .px-md-5 { + padding-right: 3rem!important + } + .pl-md-5, + .px-md-5 { + padding-left: 3rem!important + } + .pt-md-5, + .py-md-5 { + padding-top: 3rem!important + } + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem!important + } + .p-md-5 { + padding: 3rem!important + } + .m-md-auto { + margin: auto!important + } +} + +@media (min-width: 992px) { + .mr-lg-0, + .mx-lg-0 { + margin-right: 0!important + } + .ml-lg-0, + .mx-lg-0 { + margin-left: 0!important + } + .mt-lg-0, + .my-lg-0 { + margin-top: 0!important + } + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0!important + } + .pr-lg-0, + .px-lg-0 { + padding-right: 0!important + } + .pl-lg-0, + .px-lg-0 { + padding-left: 0!important + } + .pt-lg-0, + .py-lg-0 { + padding-top: 0!important + } + .pb-lg-0, + .py-lg-0 { + padding-bottom: 0!important + } + .m-lg-0 { + margin: 0!important + } + .mr-lg-1, + .mx-lg-1 { + margin-right: .25rem!important + } + .ml-lg-1, + .mx-lg-1 { + margin-left: .25rem!important + } + .mt-lg-1, + .my-lg-1 { + margin-top: .25rem!important + } + .mb-lg-1, + .my-lg-1 { + margin-bottom: .25rem!important + } + .m-lg-1 { + margin: .25rem!important + } + .mr-lg-2, + .mx-lg-2 { + margin-right: .5rem!important + } + .ml-lg-2, + .mx-lg-2 { + margin-left: .5rem!important + } + .mt-lg-2, + .my-lg-2 { + margin-top: .5rem!important + } + .mb-lg-2, + .my-lg-2 { + margin-bottom: .5rem!important + } + .m-lg-2 { + margin: .5rem!important + } + .mr-lg-3, + .mx-lg-3 { + margin-right: 1rem!important + } + .ml-lg-3, + .mx-lg-3 { + margin-left: 1rem!important + } + .mt-lg-3, + .my-lg-3 { + margin-top: 1rem!important + } + .mb-lg-3, + .my-lg-3 { + margin-bottom: 1rem!important + } + .m-lg-3 { + margin: 1rem!important + } + .mr-lg-4, + .mx-lg-4 { + margin-right: 1.5rem!important + } + .ml-lg-4, + .mx-lg-4 { + margin-left: 1.5rem!important + } + .mt-lg-4, + .my-lg-4 { + margin-top: 1.5rem!important + } + .mb-lg-4, + .my-lg-4 { + margin-bottom: 1.5rem!important + } + .m-lg-4 { + margin: 1.5rem!important + } + .mr-lg-5, + .mx-lg-5 { + margin-right: 3rem!important + } + .ml-lg-5, + .mx-lg-5 { + margin-left: 3rem!important + } + .mt-lg-5, + .my-lg-5 { + margin-top: 3rem!important + } + .mb-lg-5, + .my-lg-5 { + margin-bottom: 3rem!important + } + .m-lg-5 { + margin: 3rem!important + } + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto!important + } + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto!important + } + .mt-lg-auto, + .my-lg-auto { + margin-top: auto!important + } + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto!important + } + .p-lg-0 { + padding: 0!important + } + .pr-lg-1, + .px-lg-1 { + padding-right: .25rem!important + } + .pl-lg-1, + .px-lg-1 { + padding-left: .25rem!important + } + .pt-lg-1, + .py-lg-1 { + padding-top: .25rem!important + } + .pb-lg-1, + .py-lg-1 { + padding-bottom: .25rem!important + } + .p-lg-1 { + padding: .25rem!important + } + .pr-lg-2, + .px-lg-2 { + padding-right: .5rem!important + } + .pl-lg-2, + .px-lg-2 { + padding-left: .5rem!important + } + .pt-lg-2, + .py-lg-2 { + padding-top: .5rem!important + } + .pb-lg-2, + .py-lg-2 { + padding-bottom: .5rem!important + } + .p-lg-2 { + padding: .5rem!important + } + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem!important + } + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem!important + } + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem!important + } + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem!important + } + .p-lg-3 { + padding: 1rem!important + } + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem!important + } + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem!important + } + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem!important + } + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem!important + } + .p-lg-4 { + padding: 1.5rem!important + } + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem!important + } + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem!important + } + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem!important + } + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem!important + } + .p-lg-5 { + padding: 3rem!important + } + .m-lg-auto { + margin: auto!important + } +} + +@media (min-width: 1200px) { + .mr-xl-0, + .mx-xl-0 { + margin-right: 0!important + } + .ml-xl-0, + .mx-xl-0 { + margin-left: 0!important + } + .mt-xl-0, + .my-xl-0 { + margin-top: 0!important + } + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0!important + } + .pr-xl-0, + .px-xl-0 { + padding-right: 0!important + } + .pl-xl-0, + .px-xl-0 { + padding-left: 0!important + } + .pt-xl-0, + .py-xl-0 { + padding-top: 0!important + } + .pb-xl-0, + .py-xl-0 { + padding-bottom: 0!important + } + .m-xl-0 { + margin: 0!important + } + .mr-xl-1, + .mx-xl-1 { + margin-right: .25rem!important + } + .ml-xl-1, + .mx-xl-1 { + margin-left: .25rem!important + } + .mt-xl-1, + .my-xl-1 { + margin-top: .25rem!important + } + .mb-xl-1, + .my-xl-1 { + margin-bottom: .25rem!important + } + .m-xl-1 { + margin: .25rem!important + } + .mr-xl-2, + .mx-xl-2 { + margin-right: .5rem!important + } + .ml-xl-2, + .mx-xl-2 { + margin-left: .5rem!important + } + .mt-xl-2, + .my-xl-2 { + margin-top: .5rem!important + } + .mb-xl-2, + .my-xl-2 { + margin-bottom: .5rem!important + } + .m-xl-2 { + margin: .5rem!important + } + .mr-xl-3, + .mx-xl-3 { + margin-right: 1rem!important + } + .ml-xl-3, + .mx-xl-3 { + margin-left: 1rem!important + } + .mt-xl-3, + .my-xl-3 { + margin-top: 1rem!important + } + .mb-xl-3, + .my-xl-3 { + margin-bottom: 1rem!important + } + .m-xl-3 { + margin: 1rem!important + } + .mr-xl-4, + .mx-xl-4 { + margin-right: 1.5rem!important + } + .ml-xl-4, + .mx-xl-4 { + margin-left: 1.5rem!important + } + .mt-xl-4, + .my-xl-4 { + margin-top: 1.5rem!important + } + .mb-xl-4, + .my-xl-4 { + margin-bottom: 1.5rem!important + } + .m-xl-4 { + margin: 1.5rem!important + } + .mr-xl-5, + .mx-xl-5 { + margin-right: 3rem!important + } + .ml-xl-5, + .mx-xl-5 { + margin-left: 3rem!important + } + .mt-xl-5, + .my-xl-5 { + margin-top: 3rem!important + } + .mb-xl-5, + .my-xl-5 { + margin-bottom: 3rem!important + } + .m-xl-5 { + margin: 3rem!important + } + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto!important + } + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto!important + } + .mt-xl-auto, + .my-xl-auto { + margin-top: auto!important + } + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto!important + } + .p-xl-0 { + padding: 0!important + } + .pr-xl-1, + .px-xl-1 { + padding-right: .25rem!important + } + .pl-xl-1, + .px-xl-1 { + padding-left: .25rem!important + } + .pt-xl-1, + .py-xl-1 { + padding-top: .25rem!important + } + .pb-xl-1, + .py-xl-1 { + padding-bottom: .25rem!important + } + .p-xl-1 { + padding: .25rem!important + } + .pr-xl-2, + .px-xl-2 { + padding-right: .5rem!important + } + .pl-xl-2, + .px-xl-2 { + padding-left: .5rem!important + } + .pt-xl-2, + .py-xl-2 { + padding-top: .5rem!important + } + .pb-xl-2, + .py-xl-2 { + padding-bottom: .5rem!important + } + .p-xl-2 { + padding: .5rem!important + } + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem!important + } + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem!important + } + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem!important + } + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem!important + } + .p-xl-3 { + padding: 1rem!important + } + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem!important + } + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem!important + } + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem!important + } + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem!important + } + .p-xl-4 { + padding: 1.5rem!important + } + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem!important + } + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem!important + } + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem!important + } + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem!important + } + .p-xl-5 { + padding: 3rem!important + } + .m-xl-auto { + margin: auto!important + } +} + +.e-px { + padding-left: 0; + padding-right: 0 +} + +@media (min-width: 576px) { + .e-px { + padding-left: 5%; + padding-right: 5% + } +} + +@media (min-width: 768px) { + .e-px { + padding-left: 10%; + padding-right: 10% + } +} + +.comments-list img, +.img-fluid, +.modal-dialog.cascading-modal.modal-avatar .modal-header, +.reply-form img, +.section-blog-fw .view img { + max-width: 100%; + height: auto +} + +.inline-ul>li { + display: inline +} + +.list-inline-div>div { + display: inline-block +} + +@media only screen and (max-width: 992px) { + .center-on-small-only { + text-align: center + } + .center-on-small-only .comments-list img, + .center-on-small-only .img-fluid, + .center-on-small-only .modal-dialog.cascading-modal.modal-avatar .modal-header, + .center-on-small-only .reply-form img, + .center-on-small-only .section-blog-fw .view img, + .comments-list .center-on-small-only img, + .modal-dialog.cascading-modal.modal-avatar .center-on-small-only .modal-header, + .reply-form .center-on-small-only img, + .section-blog-fw .view .center-on-small-only img { + display: inline + } +} + +.card .card-circle, +.card-overlay, +.flex-center, +.section.team-section .avatar, +.testimonial-carousel .testimonial .avatar { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + height: 100% +} + +.divider-new:after, +.divider-new:before { + content: ''; + height: 1.5px; + background: #c6c6c6 +} + +.card .card-circle p, +.card-overlay p, +.flex-center p, +.section.team-section .avatar p, +.testimonial-carousel .testimonial .avatar p { + margin: 0 +} + +.card .card-circle ul li, +.card-overlay ul li, +.flex-center ul li, +.section.team-section .avatar ul li, +.testimonial-carousel .testimonial .avatar ul li { + margin-bottom: 1rem +} + +@media (min-width: 992px) { + .e-px { + padding-left: 15%; + padding-right: 15% + } + .mb-r { + margin-bottom: 3rem!important + } +} + +@media (max-width: 992px) { + .hidden-md-down { + display: none!important + } + .mb-r { + margin-bottom: 2rem!important + } + .navbar .container { + width: 100% + } + .navbar .container .navbar-toggler-right { + right: 0 + } +} + +.font-bold { + font-weight: 500 +} + +.hr-light { + border-top: 1px solid #fff +} + +.hr-dark { + border-top: 1px solid #666 +} + +.blockquote .bq-title { + font-weight: 400; + font-size: 1.5rem; + margin-bottom: 0 +} + +.divider-new, +body, +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: 300 +} + +.blockquote p { + font-size: 1.1rem +} + +.bq-primary { + border-left: 3px solid #4285F4 +} + +.bq-primary .bq-title { + color: #4285F4 +} + +.bq-warning { + border-left: 3px solid #fb3 +} + +.bq-warning .bq-title { + color: #fb3 +} + +.bq-danger { + border-left: 3px solid #ff3547 +} + +.bq-danger .bq-title { + color: #ff3547 +} + +.bq-success { + border-left: 3px solid #00C851 +} + +.bq-success .bq-title { + color: #00C851 +} + +@font-face { + font-family: "Swiss 721 W01 Thin"; + src: url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.eot"); + src: url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.eot?#iefix") format("embedded-opentype"), url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.woff") format("woff"), url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.ttf") format("truetype"), url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.svg#swis721_th_btthin") format("svg"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: "Swiss 721 W01 Light"; + src: url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.eot"); + src: url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.eot?#iefix") format("embedded-opentype"), url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.woff") format("woff"), url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.ttf") format("truetype"), url("https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.svg#swis721_lt_btlight") format("svg"); + font-weight: normal; + font-style: normal; +} + + +/* @font-face { + font-family: Roboto; + src: url(../font/roboto/Roboto-Thin.eot); + src: url(../font/roboto/Roboto-Thin.eot?#iefix) format("embedded-opentype"), url(../font/roboto/Roboto-Thin.woff2) format("woff2"), url(../font/roboto/Roboto-Thin.woff) format("woff"), url(../font/roboto/Roboto-Thin.ttf) format("truetype"); + font-weight: 200 +} + +@font-face { + font-family: Roboto; + src: url(../font/roboto/Roboto-Light.eot); + src: url(../font/roboto/Roboto-Light.eot?#iefix) format("embedded-opentype"), url(../font/roboto/Roboto-Light.woff2) format("woff2"), url(../font/roboto/Roboto-Light.woff) format("woff"), url(../font/roboto/Roboto-Light.ttf) format("truetype"); + font-weight: 300 +} + +@font-face { + font-family: Roboto; + src: url(../font/roboto/Roboto-Regular.eot); + src: url(../font/roboto/Roboto-Regular.eot?#iefix) format("embedded-opentype"), url(../font/roboto/Roboto-Regular.woff2) format("woff2"), url(../font/roboto/Roboto-Regular.woff) format("woff"), url(../font/roboto/Roboto-Regular.ttf) format("truetype"); + font-weight: 400 +} + +@font-face { + font-family: Roboto; + src: url(../font/roboto/Roboto-Medium.eot); + src: url(../font/roboto/Roboto-Medium.eot?#iefix) format("embedded-opentype"), url(../font/roboto/Roboto-Medium.woff2) format("woff2"), url(../font/roboto/Roboto-Medium.woff) format("woff"), url(../font/roboto/Roboto-Medium.ttf) format("truetype"); + font-weight: 500 +} + +@font-face { + font-family: Roboto; + src: url(../font/roboto/Roboto-Bold.eot); + src: url(../font/roboto/Roboto-Bold.eot?#iefix) format("embedded-opentype"), url(../font/roboto/Roboto-Bold.woff2) format("woff2"), url(../font/roboto/Roboto-Bold.woff) format("woff"), url(../font/roboto/Roboto-Bold.ttf) format("truetype"); + font-weight: 700 +} +*/ + +body { + font-family: Roboto, "Swiss 721 W01 Thin", sans-serif +} + +.h1-responsive, +.section-heading h1 { + font-size: 150% +} + +.h2-responsive, +.section-blog-fw h2 { + font-size: 145% +} + +.h3-responsive, +.h4-responsive, +.h5-responsive { + font-size: 135% +} + +@media (min-width: 576px) { + .h1-responsive, + .section-heading h1 { + font-size: 170% + } + .h2-responsive, + .section-blog-fw h2 { + font-size: 140% + } + .h3-responsive, + .h4-responsive, + .h5-responsive { + font-size: 125% + } +} + +@media (min-width: 768px) { + .h1-responsive, + .section-heading h1 { + font-size: 200% + } + .h2-responsive, + .section-blog-fw h2 { + font-size: 170% + } + .h3-responsive { + font-size: 140% + } + .h4-responsive, + .h5-responsive { + font-size: 125% + } +} + +@media (min-width: 992px) { + .h1-responsive, + .section-heading h1 { + font-size: 200% + } + .h2-responsive, + .section-blog-fw h2 { + font-size: 170% + } + .h3-responsive { + font-size: 140% + } + .h4-responsive, + .h5-responsive { + font-size: 125% + } +} + +@media (min-width: 1200px) { + .e-px { + padding-left: 20%; + padding-right: 20% + } + .h1-responsive, + .section-heading h1 { + font-size: 250% + } + .h2-responsive, + .section-blog-fw h2 { + font-size: 200% + } + .h3-responsive { + font-size: 170% + } + .h4-responsive { + font-size: 140% + } + .h5-responsive { + font-size: 125% + } +} + +.fs-0 { + font-size: 0!important +} + +.fs-1 { + font-size: .25rem!important +} + +.fs-2 { + font-size: .5rem!important +} + +.fs-3 { + font-size: 1rem!important +} + +.fs-4 { + font-size: 1.5rem!important +} + +.fs-5 { + font-size: 3rem!important +} + +.divider-new { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + margin-top: 45px; + margin-bottom: 45px +} + +.card, +.card .card-body h3, +.card .card-body h4, +.card .card-text { + font-weight: 400 +} + +.divider-new h2 { + margin-top: 5px +} + +.divider-new:before { + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + margin: 0 .45em 0 0 +} + +.divider-new:after { + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + margin: 0 0 0 .45em +} + +blockquote { + padding: .5rem 1rem; + font-size: 1.25rem; + border-left: .25rem solid #eceeef +} + +blockquote p { + font-size: .9rem; + padding-left: 2rem; + padding-top: 1rem; + padding-bottom: 1rem +} + +.btn { + font-size: .8rem; + padding: .85rem 2.13rem; + margin: 6px; + border-radius: 2px; + border: 0; + -webkit-transition: .2s ease-out; + transition: .2s ease-out; + white-space: normal!important; + word-wrap: break-word; + cursor: pointer +} + +.btn:active, +.btn:focus, +.btn:hover { + outline: 0 +} + +.btn .fa { + font-size: 1rem; + margin-top: -2px +} + +.btn .fa.right { + margin-left: 3px +} + +.btn .fa.left { + margin-right: 3px +} + +.btn.btn-lg { + font-size: .9rem; + padding: 1rem 2.4rem +} + +.btn.btn-lg .fa { + font-size: 1.2rem +} + +.btn.btn-md { + font-size: .7rem; + padding: .7rem 1.6rem +} + +.btn.btn-md .fa { + font-size: .9rem +} + +.btn.btn-sm, +.btn.wishlist { + font-size: .6rem; + padding: .5rem 1.6rem +} + +.btn.btn-sm.btn-table, +.btn.btn-table.wishlist { + padding: .5rem .9rem +} + +.btn.btn-sm .fa, +.btn.wishlist .fa { + font-size: .7rem +} + +.btn.btn-tb { + padding: .3rem 1rem +} + +.btn.disabled, +.btn:disabled { + cursor: not-allowed; + pointer-events: none +} + +.btn[class*=btn-outline-] { + padding-top: .76rem; + padding-bottom: .76rem +} + +.btn[class*=btn-outline-].btn-sm, +.btn[class*=btn-outline-].wishlist { + padding-top: .42rem; + padding-bottom: .42rem +} + +.btn[class*=btn-outline-].btn-md { + padding-top: .58rem; + padding-bottom: .58rem +} + +.btn[class*=btn-outline-].btn-lg { + padding-top: .9rem; + padding-bottom: .9rem +} + +.btn-secondary.disabled, +.btn-secondary:disabled { + background-color: #b579d2!important; + border-color: #b579d2!important +} + +.btn-group .btn { + margin: 0 +} + +.btn-block { + margin: inherit +} + +.btn-split { + padding-left: .85rem; + padding-right: 1.25rem +} + +.btn-link, +.btn-link:focus, +.btn-link:hover { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none +} + +.btn-primary { + background-color: #4285F4 +} + +.btn-primary:hover { + background-color: #5a95f5!important +} + +.btn-primary.active, +.btn-primary:active, +.btn-primary:focus { + background-color: #0d5bdd!important +} + +.btn-primary.dropdown-toggle { + background-color: #4285F4!important +} + +.btn-primary.dropdown-toggle:focus, +.btn-primary.dropdown-toggle:hover { + background-color: #5a95f5!important +} + +.btn-outline-primary { + border: 2px solid #4285F4; + color: #4285F4!important; + background-color: transparent +} + +.btn-outline-primary.active, +.btn-outline-primary:active, +.btn-outline-primary:active:focus, +.btn-outline-primary:focus, +.btn-outline-primary:hover { + background-color: transparent; + color: #4285F4; + border-color: #4285F4 +} + +.btn-danger { + background-color: #ff3547 +} + +.btn-danger:hover { + background-color: #ff4f5e!important +} + +.btn-danger.active, +.btn-danger:active, +.btn-danger:focus { + background-color: #e80015!important +} + +.btn-danger.dropdown-toggle { + background-color: #ff3547!important +} + +.btn-danger.dropdown-toggle:focus, +.btn-danger.dropdown-toggle:hover { + background-color: #ff4f5e!important +} + +.btn-outline-danger { + border: 2px solid #ff3547; + color: #ff3547!important; + background-color: transparent +} + +.btn-outline-danger.active, +.btn-outline-danger:active, +.btn-outline-danger:active:focus, +.btn-outline-danger:focus, +.btn-outline-danger:hover { + background-color: transparent; + color: #ff3547; + border-color: #ff3547 +} + +.btn-warning { + background-color: #F80 +} + +.btn-warning:hover { + background-color: #ff941a!important +} + +.btn-warning.active, +.btn-warning:active, +.btn-warning:focus { + background-color: #b35f00!important +} + +.btn-warning.dropdown-toggle { + background-color: #F80!important +} + +.btn-warning.dropdown-toggle:focus, +.btn-warning.dropdown-toggle:hover { + background-color: #ff941a!important +} + +.btn-outline-warning { + border: 2px solid #F80; + color: #F80!important; + background-color: transparent +} + +.btn-outline-warning.active, +.btn-outline-warning:active, +.btn-outline-warning:active:focus, +.btn-outline-warning:focus, +.btn-outline-warning:hover { + background-color: transparent; + color: #F80; + border-color: #F80 +} + +.btn-success { + background-color: #00C851 +} + +.btn-success:hover { + background-color: #00e25b!important +} + +.btn-success.active, +.btn-success:active, +.btn-success:focus { + background-color: #007c32!important +} + +.btn-success.dropdown-toggle { + background-color: #00C851!important +} + +.btn-success.dropdown-toggle:focus, +.btn-success.dropdown-toggle:hover { + background-color: #00e25b!important +} + +.btn-outline-success { + border: 2px solid #00C851; + color: #00C851!important; + background-color: transparent +} + +.btn-outline-success.active, +.btn-outline-success:active, +.btn-outline-success:active:focus, +.btn-outline-success:focus, +.btn-outline-success:hover { + background-color: transparent; + color: #00C851; + border-color: #00C851 +} + +.btn-info { + background-color: #33b5e5 +} + +.btn-info:hover { + background-color: #4abde8!important +} + +.btn-info.active, +.btn-info:active, +.btn-info:focus { + background-color: #178ab4!important +} + +.btn-info.dropdown-toggle { + background-color: #33b5e5!important +} + +.btn-info.dropdown-toggle:focus, +.btn-info.dropdown-toggle:hover { + background-color: #4abde8!important +} + +.btn-outline-info { + border: 2px solid #33b5e5; + color: #33b5e5!important; + background-color: transparent +} + +.btn-outline-info.active, +.btn-outline-info:active, +.btn-outline-info:active:focus, +.btn-outline-info:focus, +.btn-outline-info:hover { + background-color: transparent; + color: #33b5e5; + border-color: #33b5e5 +} + +.btn-default { + background-color: #2BBBAD +} + +.btn-default:hover { + background-color: #30cfc0!important +} + +.btn-default.active, +.btn-default:active, +.btn-default:focus { + background-color: #1d7d73!important +} + +.btn-default.dropdown-toggle { + background-color: #2BBBAD!important +} + +.btn-default.dropdown-toggle:focus, +.btn-default.dropdown-toggle:hover { + background-color: #30cfc0!important +} + +.btn-outline-default { + border: 2px solid #2BBBAD; + color: #2BBBAD!important; + background-color: transparent +} + +.btn-outline-default.active, +.btn-outline-default:active, +.btn-outline-default:active:focus, +.btn-outline-default:focus, +.btn-outline-default:hover { + background-color: transparent; + color: #2BBBAD; + border-color: #2BBBAD +} + +.btn-secondary { + background-color: #a6c +} + +.btn-secondary:hover { + background-color: #b579d2!important +} + +.btn-secondary.active, +.btn-secondary:active, +.btn-secondary:focus { + background-color: #8639ac!important +} + +.btn-secondary.dropdown-toggle { + background-color: #a6c!important +} + +.btn-secondary.dropdown-toggle:focus, +.btn-secondary.dropdown-toggle:hover { + background-color: #b579d2!important +} + +.btn-outline-secondary { + border: 2px solid #a6c; + color: #a6c!important; + background-color: transparent +} + +.btn-outline-secondary.active, +.btn-outline-secondary:active, +.btn-outline-secondary:active:focus, +.btn-outline-secondary:focus, +.btn-outline-secondary:hover { + background-color: transparent; + color: #a6c; + border-color: #a6c +} + +.btn-elegant { + background-color: #2E2E2E +} + +.btn-elegant:hover { + background-color: #3b3b3b!important +} + +.btn-elegant.active, +.btn-elegant:active, +.btn-elegant:focus { + background-color: #080808!important +} + +.btn-elegant.dropdown-toggle { + background-color: #2E2E2E!important +} + +.btn-elegant.dropdown-toggle:focus, +.btn-elegant.dropdown-toggle:hover { + background-color: #3b3b3b!important +} + +.btn-outline-elegant { + border: 2px solid #2E2E2E; + color: #2E2E2E!important; + background-color: transparent +} + +.btn-outline-elegant.active, +.btn-outline-elegant:active, +.btn-outline-elegant:active:focus, +.btn-outline-elegant:focus, +.btn-outline-elegant:hover { + background-color: transparent; + color: #2E2E2E; + border-color: #2E2E2E +} + +.btn-unique { + background-color: #880e4f +} + +.btn-unique:hover { + background-color: #9f105c!important +} + +.btn-unique.active, +.btn-unique:active, +.btn-unique:focus { + background-color: #430727!important +} + +.btn-unique.dropdown-toggle { + background-color: #880e4f!important +} + +.btn-unique.dropdown-toggle:focus, +.btn-unique.dropdown-toggle:hover { + background-color: #9f105c!important +} + +.btn-outline-unique { + border: 2px solid #880e4f; + color: #880e4f!important; + background-color: transparent +} + +.btn-outline-unique.active, +.btn-outline-unique:active, +.btn-outline-unique:active:focus, +.btn-outline-unique:focus, +.btn-outline-unique:hover { + background-color: transparent; + color: #880e4f; + border-color: #880e4f +} + +.btn-dark-green { + background-color: #388E3C +} + +.btn-dark-green:hover { + background-color: #3fa044!important +} + +.btn-dark-green.active, +.btn-dark-green:active, +.btn-dark-green:focus { + background-color: #225725!important +} + +.btn-dark-green.dropdown-toggle { + background-color: #388E3C!important +} + +.btn-dark-green.dropdown-toggle:focus, +.btn-dark-green.dropdown-toggle:hover { + background-color: #3fa044!important +} + +.btn-outline-dark-green { + border: 2px solid #388E3C; + color: #388E3C!important; + background-color: transparent +} + +.btn-outline-dark-green.active, +.btn-outline-dark-green:active, +.btn-outline-dark-green:active:focus, +.btn-outline-dark-green:focus, +.btn-outline-dark-green:hover { + background-color: transparent; + color: #388E3C; + border-color: #388E3C +} + +.btn-mdb-color { + background-color: #59698D +} + +.btn-mdb-color:hover { + background-color: #63759d!important +} + +.btn-mdb-color.active, +.btn-mdb-color:active, +.btn-mdb-color:focus { + background-color: #3b465e!important +} + +.btn-mdb-color.dropdown-toggle { + background-color: #59698D!important +} + +.btn-mdb-color.dropdown-toggle:focus, +.btn-mdb-color.dropdown-toggle:hover { + background-color: #63759d!important +} + +.btn-outline-mdb-color { + border: 2px solid #59698D; + color: #59698D!important; + background-color: transparent +} + +.btn-outline-mdb-color.active, +.btn-outline-mdb-color:active, +.btn-outline-mdb-color:active:focus, +.btn-outline-mdb-color:focus, +.btn-outline-mdb-color:hover { + background-color: transparent; + color: #59698D; + border-color: #59698D +} + +.btn-red { + background-color: #D32F2F +} + +.btn-red:hover { + background-color: #d74444!important +} + +.btn-red.active, +.btn-red:active, +.btn-red:focus { + background-color: #962020!important +} + +.btn-red.dropdown-toggle { + background-color: #D32F2F!important +} + +.btn-red.dropdown-toggle:focus, +.btn-red.dropdown-toggle:hover { + background-color: #d74444!important +} + +.btn-outline-red { + border: 2px solid #D32F2F; + color: #D32F2F!important; + background-color: transparent +} + +.btn-outline-red.active, +.btn-outline-red:active, +.btn-outline-red:active:focus, +.btn-outline-red:focus, +.btn-outline-red:hover { + background-color: transparent; + color: #D32F2F; + border-color: #D32F2F +} + +.btn-pink { + background-color: #ec407a +} + +.btn-pink:hover { + background-color: #ee578a!important +} + +.btn-pink.active, +.btn-pink:active, +.btn-pink:focus { + background-color: #cb1452!important +} + +.btn-pink.dropdown-toggle { + background-color: #ec407a!important +} + +.btn-pink.dropdown-toggle:focus, +.btn-pink.dropdown-toggle:hover { + background-color: #ee578a!important +} + +.btn-outline-pink { + border: 2px solid #ec407a; + color: #ec407a!important; + background-color: transparent +} + +.btn-outline-pink.active, +.btn-outline-pink:active, +.btn-outline-pink:active:focus, +.btn-outline-pink:focus, +.btn-outline-pink:hover { + background-color: transparent; + color: #ec407a; + border-color: #ec407a +} + +.btn-purple { + background-color: #8e24aa +} + +.btn-purple:hover { + background-color: #a028bf!important +} + +.btn-purple.active, +.btn-purple:active, +.btn-purple:focus { + background-color: #59176b!important +} + +.btn-purple.dropdown-toggle { + background-color: #8e24aa!important +} + +.btn-purple.dropdown-toggle:focus, +.btn-purple.dropdown-toggle:hover { + background-color: #a028bf!important +} + +.btn-outline-purple { + border: 2px solid #8e24aa; + color: #8e24aa!important; + background-color: transparent +} + +.btn-outline-purple.active, +.btn-outline-purple:active, +.btn-outline-purple:active:focus, +.btn-outline-purple:focus, +.btn-outline-purple:hover { + background-color: transparent; + color: #8e24aa; + border-color: #8e24aa +} + +.btn-deep-purple { + background-color: #512da8 +} + +.btn-deep-purple:hover { + background-color: #5b32bc!important +} + +.btn-deep-purple.active, +.btn-deep-purple:active, +.btn-deep-purple:focus { + background-color: #341d6c!important +} + +.btn-deep-purple.dropdown-toggle { + background-color: #512da8!important +} + +.btn-deep-purple.dropdown-toggle:focus, +.btn-deep-purple.dropdown-toggle:hover { + background-color: #5b32bc!important +} + +.btn-outline-deep-purple { + border: 2px solid #512da8; + color: #512da8!important; + background-color: transparent +} + +.btn-outline-deep-purple.active, +.btn-outline-deep-purple:active, +.btn-outline-deep-purple:active:focus, +.btn-outline-deep-purple:focus, +.btn-outline-deep-purple:hover { + background-color: transparent; + color: #512da8; + border-color: #512da8 +} + +.btn-indigo { + background-color: #3f51b5 +} + +.btn-indigo:hover { + background-color: #4d5ec1!important +} + +.btn-indigo.active, +.btn-indigo:active, +.btn-indigo:focus { + background-color: #2b387c!important +} + +.btn-indigo.dropdown-toggle { + background-color: #3f51b5!important +} + +.btn-indigo.dropdown-toggle:focus, +.btn-indigo.dropdown-toggle:hover { + background-color: #4d5ec1!important +} + +.btn-outline-indigo { + border: 2px solid #3f51b5; + color: #3f51b5!important; + background-color: transparent +} + +.btn-outline-indigo.active, +.btn-outline-indigo:active, +.btn-outline-indigo:active:focus, +.btn-outline-indigo:focus, +.btn-outline-indigo:hover { + background-color: transparent; + color: #3f51b5; + border-color: #3f51b5 +} + +.btn-blue { + background-color: #1976D2 +} + +.btn-blue:hover { + background-color: #2083e4!important +} + +.btn-blue.active, +.btn-blue:active, +.btn-blue:focus { + background-color: #11508e!important +} + +.btn-blue.dropdown-toggle { + background-color: #1976D2!important +} + +.btn-blue.dropdown-toggle:focus, +.btn-blue.dropdown-toggle:hover { + background-color: #2083e4!important +} + +.btn-outline-blue { + border: 2px solid #1976D2; + color: #1976D2!important; + background-color: transparent +} + +.btn-outline-blue.active, +.btn-outline-blue:active, +.btn-outline-blue:active:focus, +.btn-outline-blue:focus, +.btn-outline-blue:hover { + background-color: transparent; + color: #1976D2; + border-color: #1976D2 +} + +.btn-light-blue { + background-color: #82B1FF +} + +.btn-light-blue:hover { + background-color: #9cc1ff!important +} + +.btn-light-blue.active, +.btn-light-blue:active, +.btn-light-blue:focus { + background-color: #3681ff!important +} + +.btn-light-blue.dropdown-toggle { + background-color: #82B1FF!important +} + +.btn-light-blue.dropdown-toggle:focus, +.btn-light-blue.dropdown-toggle:hover { + background-color: #9cc1ff!important +} + +.btn-outline-light-blue { + border: 2px solid #82B1FF; + color: #82B1FF!important; + background-color: transparent +} + +.btn-outline-light-blue.active, +.btn-outline-light-blue:active, +.btn-outline-light-blue:active:focus, +.btn-outline-light-blue:focus, +.btn-outline-light-blue:hover { + background-color: transparent; + color: #82B1FF; + border-color: #82B1FF +} + +.btn-cyan { + background-color: #00bcd4 +} + +.btn-cyan:hover { + background-color: #00d3ee!important +} + +.btn-cyan.active, +.btn-cyan:active, +.btn-cyan:focus { + background-color: #007888!important +} + +.btn-cyan.dropdown-toggle { + background-color: #00bcd4!important +} + +.btn-cyan.dropdown-toggle:focus, +.btn-cyan.dropdown-toggle:hover { + background-color: #00d3ee!important +} + +.btn-outline-cyan { + border: 2px solid #00bcd4; + color: #00bcd4!important; + background-color: transparent +} + +.btn-outline-cyan.active, +.btn-outline-cyan:active, +.btn-outline-cyan:active:focus, +.btn-outline-cyan:focus, +.btn-outline-cyan:hover { + background-color: transparent; + color: #00bcd4; + border-color: #00bcd4 +} + +.btn-teal { + background-color: #00796b +} + +.btn-teal:hover { + background-color: #009382!important +} + +.btn-teal.active, +.btn-teal:active, +.btn-teal:focus { + background-color: #002d27!important +} + +.btn-teal.dropdown-toggle { + background-color: #00796b!important +} + +.btn-teal.dropdown-toggle:focus, +.btn-teal.dropdown-toggle:hover { + background-color: #009382!important +} + +.btn-outline-teal { + border: 2px solid #00796b; + color: #00796b!important; + background-color: transparent +} + +.btn-outline-teal.active, +.btn-outline-teal:active, +.btn-outline-teal:active:focus, +.btn-outline-teal:focus, +.btn-outline-teal:hover { + background-color: transparent; + color: #00796b; + border-color: #00796b +} + +.btn-green { + background-color: #388E3C +} + +.btn-green:hover { + background-color: #3fa044!important +} + +.btn-green.active, +.btn-green:active, +.btn-green:focus { + background-color: #225725!important +} + +.btn-green.dropdown-toggle { + background-color: #388E3C!important +} + +.btn-green.dropdown-toggle:focus, +.btn-green.dropdown-toggle:hover { + background-color: #3fa044!important +} + +.btn-outline-green { + border: 2px solid #388E3C; + color: #388E3C!important; + background-color: transparent +} + +.btn-outline-green.active, +.btn-outline-green:active, +.btn-outline-green:active:focus, +.btn-outline-green:focus, +.btn-outline-green:hover { + background-color: transparent; + color: #388E3C; + border-color: #388E3C +} + +.btn-light-green { + background-color: #8bc34a +} + +.btn-light-green:hover { + background-color: #97c95d!important +} + +.btn-light-green.active, +.btn-light-green:active, +.btn-light-green:focus { + background-color: #649130!important +} + +.btn-light-green.dropdown-toggle { + background-color: #8bc34a!important +} + +.btn-light-green.dropdown-toggle:focus, +.btn-light-green.dropdown-toggle:hover { + background-color: #97c95d!important +} + +.btn-outline-light-green { + border: 2px solid #8bc34a; + color: #8bc34a!important; + background-color: transparent +} + +.btn-outline-light-green.active, +.btn-outline-light-green:active, +.btn-outline-light-green:active:focus, +.btn-outline-light-green:focus, +.btn-outline-light-green:hover { + background-color: transparent; + color: #8bc34a; + border-color: #8bc34a +} + +.btn-lime { + background-color: #afb42b +} + +.btn-lime:hover { + background-color: #c3c930!important +} + +.btn-lime.active, +.btn-lime:active, +.btn-lime:focus { + background-color: #73761c!important +} + +.btn-lime.dropdown-toggle { + background-color: #afb42b!important +} + +.btn-lime.dropdown-toggle:focus, +.btn-lime.dropdown-toggle:hover { + background-color: #c3c930!important +} + +.btn-outline-lime { + border: 2px solid #afb42b; + color: #afb42b!important; + background-color: transparent +} + +.btn-outline-lime.active, +.btn-outline-lime:active, +.btn-outline-lime:active:focus, +.btn-outline-lime:focus, +.btn-outline-lime:hover { + background-color: transparent; + color: #afb42b; + border-color: #afb42b +} + +.btn-yellow { + background-color: #fbc02d +} + +.btn-yellow:hover { + background-color: #fbc846!important +} + +.btn-yellow.active, +.btn-yellow:active, +.btn-yellow:focus { + background-color: #d79b04!important +} + +.btn-yellow.dropdown-toggle { + background-color: #fbc02d!important +} + +.btn-yellow.dropdown-toggle:focus, +.btn-yellow.dropdown-toggle:hover { + background-color: #fbc846!important +} + +.btn-outline-yellow { + border: 2px solid #fbc02d; + color: #fbc02d!important; + background-color: transparent +} + +.btn-outline-yellow.active, +.btn-outline-yellow:active, +.btn-outline-yellow:active:focus, +.btn-outline-yellow:focus, +.btn-outline-yellow:hover { + background-color: transparent; + color: #fbc02d; + border-color: #fbc02d +} + +.btn-amber { + background-color: #ffa000 +} + +.btn-amber:hover { + background-color: #ffaa1a!important +} + +.btn-amber.active, +.btn-amber:active, +.btn-amber:focus { + background-color: #b37000!important +} + +.btn-amber.dropdown-toggle { + background-color: #ffa000!important +} + +.btn-amber.dropdown-toggle:focus, +.btn-amber.dropdown-toggle:hover { + background-color: #ffaa1a!important +} + +.btn-outline-amber { + border: 2px solid #ffa000; + color: #ffa000!important; + background-color: transparent +} + +.btn-outline-amber.active, +.btn-outline-amber:active, +.btn-outline-amber:active:focus, +.btn-outline-amber:focus, +.btn-outline-amber:hover { + background-color: transparent; + color: #ffa000; + border-color: #ffa000 +} + +.btn-orange { + background-color: #f57c00 +} + +.btn-orange:hover { + background-color: #ff8910!important +} + +.btn-orange.active, +.btn-orange:active, +.btn-orange:focus { + background-color: #a95500!important +} + +.btn-orange.dropdown-toggle { + background-color: #f57c00!important +} + +.btn-orange.dropdown-toggle:focus, +.btn-orange.dropdown-toggle:hover { + background-color: #ff8910!important +} + +.btn-outline-orange { + border: 2px solid #f57c00; + color: #f57c00!important; + background-color: transparent +} + +.btn-outline-orange.active, +.btn-outline-orange:active, +.btn-outline-orange:active:focus, +.btn-outline-orange:focus, +.btn-outline-orange:hover { + background-color: transparent; + color: #f57c00; + border-color: #f57c00 +} + +.btn-deep-orange { + background-color: #ff7043 +} + +.btn-deep-orange:hover { + background-color: #ff835d!important +} + +.btn-deep-orange.active, +.btn-deep-orange:active, +.btn-deep-orange:focus { + background-color: #f63b00!important +} + +.btn-deep-orange.dropdown-toggle { + background-color: #ff7043!important +} + +.btn-deep-orange.dropdown-toggle:focus, +.btn-deep-orange.dropdown-toggle:hover { + background-color: #ff835d!important +} + +.btn-outline-deep-orange { + border: 2px solid #ff7043; + color: #ff7043!important; + background-color: transparent +} + +.btn-outline-deep-orange.active, +.btn-outline-deep-orange:active, +.btn-outline-deep-orange:active:focus, +.btn-outline-deep-orange:focus, +.btn-outline-deep-orange:hover { + background-color: transparent; + color: #ff7043; + border-color: #ff7043 +} + +.btn-brown { + background-color: #795548 +} + +.btn-brown:hover { + background-color: #896052!important +} + +.btn-brown.active, +.btn-brown:active, +.btn-brown:focus { + background-color: #49332b!important +} + +.btn-brown.dropdown-toggle { + background-color: #795548!important +} + +.btn-brown.dropdown-toggle:focus, +.btn-brown.dropdown-toggle:hover { + background-color: #896052!important +} + +.btn-outline-brown { + border: 2px solid #795548; + color: #795548!important; + background-color: transparent +} + +.btn-outline-brown.active, +.btn-outline-brown:active, +.btn-outline-brown:active:focus, +.btn-outline-brown:focus, +.btn-outline-brown:hover { + background-color: transparent; + color: #795548; + border-color: #795548 +} + +.btn-grey { + background-color: #616161 +} + +.btn-grey:hover { + background-color: #6e6e6e!important +} + +.btn-grey.active, +.btn-grey:active, +.btn-grey:focus { + background-color: #3b3b3b!important +} + +.btn-grey.dropdown-toggle { + background-color: #616161!important +} + +.btn-grey.dropdown-toggle:focus, +.btn-grey.dropdown-toggle:hover { + background-color: #6e6e6e!important +} + +.btn-outline-grey { + border: 2px solid #616161; + color: #616161!important; + background-color: transparent +} + +.btn-outline-grey.active, +.btn-outline-grey:active, +.btn-outline-grey:active:focus, +.btn-outline-grey:focus, +.btn-outline-grey:hover { + background-color: transparent; + color: #616161; + border-color: #616161 +} + +.btn-blue-grey { + background-color: #78909c +} + +.btn-blue-grey:hover { + background-color: #879ca7!important +} + +.btn-blue-grey.active, +.btn-blue-grey:active, +.btn-blue-grey:focus { + background-color: #546973!important +} + +.btn-blue-grey.dropdown-toggle { + background-color: #78909c!important +} + +.btn-blue-grey.dropdown-toggle:focus, +.btn-blue-grey.dropdown-toggle:hover { + background-color: #879ca7!important +} + +.btn-outline-blue-grey { + border: 2px solid #78909c; + color: #78909c!important; + background-color: transparent +} + +.btn-outline-blue-grey.active, +.btn-outline-blue-grey:active, +.btn-outline-blue-grey:active:focus, +.btn-outline-blue-grey:focus, +.btn-outline-blue-grey:hover { + background-color: transparent; + color: #78909c; + border-color: #78909c +} + +.btn-white { + background-color: #fff +} + +.btn-white:hover { + background-color: #fff!important +} + +.btn-white.active, +.btn-white:active, +.btn-white:focus { + background-color: #d9d9d9!important +} + +.btn-white.dropdown-toggle, +.btn-white.dropdown-toggle:focus, +.btn-white.dropdown-toggle:hover { + background-color: #fff!important +} + +.btn-outline-white { + border: 2px solid #fff; + color: #fff!important; + background-color: transparent +} + +.btn-outline-white.active, +.btn-outline-white:active, +.btn-outline-white:active:focus, +.btn-outline-white:focus, +.btn-outline-white:hover { + background-color: transparent; + color: #fff; + border-color: #fff +} + +.btn-black { + background-color: #000 +} + +.btn-black:hover { + background-color: #0d0d0d!important +} + +.btn-black.active, +.btn-black.dropdown-toggle, +.btn-black:active, +.btn-black:focus { + background-color: #000!important +} + +.btn-black.dropdown-toggle:focus, +.btn-black.dropdown-toggle:hover { + background-color: #0d0d0d!important +} + +.btn-outline-black { + border: 2px solid #000; + color: #000!important; + background-color: transparent +} + +.btn-outline-black.active, +.btn-outline-black:active, +.btn-outline-black:active:focus, +.btn-outline-black:focus, +.btn-outline-black:hover { + background-color: transparent; + color: #000; + border-color: #000 +} + +.card { + border-radius: .3rem +} + +.card:not([class*=card-outline-]) { + border: 0 +} + +.card img { + border-radius: 2px 2px 0 0 +} + +.card .card-body h5 { + margin-bottom: 1rem; + font-size: 1rem; + font-weight: 400 +} + +.card .card-body p { + margin-bottom: 1rem +} + +.card .card-title a, +.card .card-title a:hover { + -webkit-transition: .3s; + transition: .3s +} + +.card .card-text { + font-size: .9rem; + color: #747373 +} + +.card .card-footer.links-light a { + font-size: 15px; + color: #757575 +} + +.card .card-footer.links-light a:hover { + color: #d50000; + -webkit-transition: .4s; + transition: .4s +} + +.card .card-footer.links-light a .fa { + font-size: 17px +} + +.dropdown .dropdown-menu .dropdown-item:active, +.dropdown .dropdown-menu .dropdown-item:focus, +.dropdown .dropdown-menu .dropdown-item:hover { + color: #1d1e1f; + background-color: #f7f7f9 +} + +.navbar { + font-weight: 300; + padding-right: 1rem!important +} + +.navbar form input { + margin: 0 5px 1px 8px; + height: 1rem +} + +.navbar .navbar-brand { + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; + overflow: visible +} + +.navbar .breadcrumb { + margin: 0; + background-color: inherit; + font-weight: 300; + font-size: 15px; + padding: .3em 0 0 1em +} + +.navbar .navbar-toggler { + border-width: 0 +} + +.navbar .nav-flex-icons, +.navbar.double-nav { + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row +} + +.navbar.navbar-dark .navbar-nav .nav-item .nav-link.disabled, +.navbar.navbar-dark .navbar-nav .nav-item .nav-link.disabled:hover { + color: rgba(255, 255, 255, .5) +} + +.navbar.navbar-light .navbar-nav .nav-item .nav-link.disabled, +.navbar.navbar-light .navbar-nav .nav-item .nav-link.disabled:hover { + color: rgba(0, 0, 0, .5) +} + +.navbar .nav-item .nav-link { + display: block +} + +.navbar .nav-item .nav-link.disabled:active { + pointer-events: none +} + +.navbar .nav-item .nav-link .fa { + padding-left: 3px; + padding-right: 3px +} + +@media (max-width: 992px) { + .navbar .nav-item .nav-link { + padding-left: 6px; + padding-right: 6px + } +} + +.navbar .dropdown-menu { + position: absolute!important; + margin-top: 0 +} + +.navbar .dropdown-menu a { + font-size: .9375rem; + font-weight: 300; + padding: 10px; + color: #000!important +} + +.navbar .dropdown-menu a:hover { + color: #fff!important +} + +@media (max-width: 600px) { + .navbar .dropdown-menu.dropdown-menu-right { + right: auto!important + } +} + +.navbar.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.9)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E"); + cursor: pointer +} + +.navbar.navbar-light .breadcrumb .nav-item .nav-link, +.navbar.navbar-light .navbar-nav .nav-item .nav-link { + color: #000; + -webkit-transition: .35s; + transition: .35s +} + +.navbar.navbar-light .breadcrumb .nav-item .nav-link:hover, +.navbar.navbar-light .navbar-nav .nav-item .nav-link:hover { + color: rgba(0, 0, 0, .75) +} + +.navbar.navbar-light .breadcrumb .nav-item.active>.nav-link:hover, +.navbar.navbar-light .navbar-nav .nav-item.active>.nav-link:hover, +.navbar.navbar-light .navbar-toggler, +.navbar.navbar-light form .form-control { + color: #000 +} + +.navbar.navbar-light .breadcrumb .nav-item.active>.nav-link, +.navbar.navbar-light .navbar-nav .nav-item.active>.nav-link { + background-color: rgba(0, 0, 0, .1) +} + +.navbar.navbar-light form input[type=text] { + border-bottom: 1px solid #000 +} + +.navbar.navbar-light form input[type=text]:focus:not([readonly]) { + border-color: #4285F4 +} + +.navbar.navbar-light form .form-control:-moz-placeholder { + color: #000; + font-weight: 300 +} + +.navbar.navbar-light form .form-control::-ms-placeholder { + color: #000; + font-weight: 300 +} + +.navbar.navbar-light form .form-control::-webkit-input-placeholder { + color: #000; + font-weight: 300 +} + +.navbar.navbar-light form .form-control::-moz-placeholder { + color: #000; + font-weight: 300 +} + +.navbar.navbar-light form .form-control:-ms-input-placeholder { + color: #000; + font-weight: 300 +} + +.navbar.navbar-light form .form-control::placeholder { + color: #000; + font-weight: 300 +} + +.navbar.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.9)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E"); + cursor: pointer +} + +.navbar.navbar-dark .breadcrumb .nav-item .nav-link, +.navbar.navbar-dark .navbar-nav .nav-item .nav-link { + color: #fff; + -webkit-transition: .35s; + transition: .35s +} + +.navbar.navbar-dark .breadcrumb .nav-item .nav-link:hover, +.navbar.navbar-dark .navbar-nav .nav-item .nav-link:hover { + color: rgba(255, 255, 255, .75) +} + +.badge, +.navbar.navbar-dark .breadcrumb .nav-item.active>.nav-link:hover, +.navbar.navbar-dark .navbar-nav .nav-item.active>.nav-link:hover, +.navbar.navbar-dark .navbar-toggler, +.navbar.navbar-dark form .form-control, +.pagination .active .page-link:hover { + color: #fff +} + +.navbar.navbar-dark .breadcrumb .nav-item.active>.nav-link, +.navbar.navbar-dark .navbar-nav .nav-item.active>.nav-link { + background-color: rgba(255, 255, 255, .1) +} + +.navbar.navbar-dark form input[type=text] { + border-bottom: 1px solid #fff +} + +.navbar.navbar-dark form input[type=text]:focus:not([readonly]) { + border-color: #4285F4 +} + +.navbar.navbar-dark form .form-control:-moz-placeholder { + color: #fff; + font-weight: 300 +} + +.navbar.navbar-dark form .form-control::-ms-placeholder { + color: #fff; + font-weight: 300 +} + +.navbar.navbar-dark form .form-control::-webkit-input-placeholder { + color: #fff; + font-weight: 300 +} + +.navbar.navbar-dark form .form-control::-moz-placeholder { + color: #fff; + font-weight: 300 +} + +.navbar.navbar-dark form .form-control:-ms-input-placeholder { + color: #fff; + font-weight: 300 +} + +.navbar.navbar-dark form .form-control::placeholder { + color: #fff; + font-weight: 300 +} + +.navbar.scrolling-navbar { + z-index: 100 +} + +@media (min-width: 600px) { + .navbar.scrolling-navbar { + -webkit-transition: background .5s ease-in-out, padding .5s ease-in-out; + transition: background .5s ease-in-out, padding .5s ease-in-out; + padding-top: 12px; + padding-bottom: 12px + } + .navbar.scrolling-navbar .navbar-nav>li { + -webkit-transition-duration: 1s; + transition-duration: 1s + } + .navbar.scrolling-navbar.top-nav-collapse { + padding-top: 5px; + padding-bottom: 5px + } + .intro-margin.view { + overflow: visible; + margin-top: -56px + } +} + +.pagination .active .page-link { + border-radius: 2px; + -webkit-transition: all .2s linear; + transition: all .2s linear +} + +.pagination.pagination-circle .page-link { + border-radius: 50%; + margin-left: 2px; + margin-right: 2px +} + +.pagination.pagination-circle .active .page-link, +.pagination.pagination-circle .page-link:hover { + border-radius: 50% +} + +.pagination .page-link { + background-color: transparent; + font-size: .8rem; + border: 0; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.pagination .page-link:hover { + -webkit-transition: all .3s linear; + transition: all .3s linear; + background-color: #eee +} + +.pagination .page-link:focus { + background-color: transparent +} + +.pagination.pg-blue .active .page-link { + background-color: #4285F4 +} + +.pagination.pg-red .active .page-link { + background-color: #ff3547 +} + +.pagination.pg-teal .active .page-link { + background-color: #2BBBAD +} + +.pagination.pg-darkgrey .active .page-link { + background-color: #37474F +} + +.pagination.pg-dark .active .page-link { + background-color: #2E2E2E +} + +.pagination.pg-bluegrey .active .page-link { + background-color: #3F729B +} + +.pagination.pg-amber .active .page-link { + background-color: #ff6f00 +} + +.pagination.pg-purple .active .page-link { + background-color: #5e35b1 +} + +.badge-primary { + background-color: #4285F4 +} + +.badge-danger { + background-color: #ff3547 +} + +.badge-warning { + background-color: #F80; + color: #FFF!important +} + +.badge-success { + background-color: #00C851 +} + +.badge-info { + background-color: #33b5e5 +} + +.badge-default { + background-color: #2BBBAD +} + +.badge-secondary { + background-color: #a6c +} + +.badge-elegant { + background-color: #2E2E2E +} + +.badge-unique { + background-color: #880e4f +} + +.badge-dark-green { + background-color: #388E3C +} + +.badge-mdb-color { + background-color: #59698D +} + +.badge-red { + background-color: #D32F2F +} + +.badge-pink { + background-color: #ec407a +} + +.badge-purple { + background-color: #8e24aa +} + +.badge-deep-purple { + background-color: #512da8 +} + +.badge-indigo { + background-color: #3f51b5 +} + +.badge-blue { + background-color: #1976D2 +} + +.badge-light-blue { + background-color: #82B1FF +} + +.badge-cyan { + background-color: #00bcd4 +} + +.badge-teal { + background-color: #00796b +} + +.badge-green { + background-color: #388E3C +} + +.badge-light-green { + background-color: #8bc34a +} + +.badge-lime { + background-color: #afb42b +} + +.badge-yellow { + background-color: #fbc02d +} + +.badge-amber { + background-color: #ffa000 +} + +.badge-orange { + background-color: #f57c00 +} + +.badge-deep-orange { + background-color: #ff7043 +} + +.badge-brown { + background-color: #795548 +} + +.badge-grey { + background-color: #616161 +} + +.badge-blue-grey { + background-color: #78909c +} + +.badge-white { + background-color: #fff +} + +.badge-black { + background-color: #000 +} + +.badge-pill { + padding-right: .6em; + padding-left: .6em; + border-radius: 10rem +} + +.modal, +body.modal-open { + padding-right: 0!important +} + +body.modal-open { + overflow: auto +} + +body.scrollable { + overflow-y: auto +} + +.modal-dialog .modal-content { + border-radius: 2px; + border: 0 +} + +@media (min-width: 768px) { + .modal .modal-dialog.modal-top { + top: 0 + } + .modal .modal-dialog.modal-left { + left: 0 + } + .modal .modal-dialog.modal-right { + right: 0 + } + .modal .modal-dialog.modal-bottom { + bottom: 0 + } + .modal .modal-dialog.modal-top-left { + top: 10px; + left: 10px + } + .modal .modal-dialog.modal-top-right { + top: 10px; + right: 10px + } + .modal .modal-dialog.modal-bottom-left { + left: 10px; + bottom: 10px + } + .modal .modal-dialog.modal-bottom-right { + right: 10px; + bottom: 10px + } +} + +.modal.fade.top:not(.show) .modal-dialog { + -webkit-transform: translate3d(0, -25%, 0); + transform: translate3d(0, -25%, 0) +} + +.modal.fade.left:not(.show) .modal-dialog { + -webkit-transform: translate3d(-25%, 0, 0); + transform: translate3d(-25%, 0, 0) +} + +.modal.fade.right:not(.show) .modal-dialog { + -webkit-transform: translate3d(25%, 0, 0); + transform: translate3d(25%, 0, 0) +} + +.modal.fade.bottom:not(.show) .modal-dialog { + -webkit-transform: translate3d(0, 25%, 0); + transform: translate3d(0, 25%, 0) +} + +@media (min-width: 992px) { + .modal .modal-fluid, + .modal .modal-frame { + width: 100%; + max-width: 100% + } + .modal.modal-scrolling { + position: relative + } + .modal.modal-scrolling .modal-dialog { + position: fixed; + z-index: 1050 + } + .modal.modal-content-clickable { + top: auto; + bottom: auto + } + .modal.modal-content-clickable .modal-dialog { + position: fixed + } + .modal .modal-fluid .modal-content { + width: 100% + } + .modal .modal-frame { + position: absolute; + margin: 0 + } + .modal .modal-frame.modal-bottom { + bottom: 0 + } + .modal .modal-full-height { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: absolute; + width: 400px; + height: 100%; + margin: 0; + top: 0; + right: 0 + } + .modal .modal-full-height.modal-bottom, + .modal .modal-full-height.modal-top { + display: block; + width: 100%; + max-width: 100%; + height: auto + } + .modal .modal-full-height.modal-top { + bottom: auto + } + .modal .modal-full-height.modal-bottom { + top: auto + } + .modal .modal-full-height .modal-content { + width: 100% + } + .modal .modal-full-height.modal-lg { + max-width: 90%; + width: 90% + } +} + +@media (min-width: 992px) and (min-width:992px) { + .modal .modal-full-height.modal-lg { + max-width: 800px; + width: 800px + } +} + +@media (min-width: 992px) and (min-width:1200px) { + .modal .modal-full-height.modal-lg { + max-width: 1000px; + width: 1000px + } +} + +@media (min-width: 992px) { + .modal .modal-side { + position: absolute; + right: 10px; + bottom: 10px; + margin: 0; + width: 400px + } +} + +.modal-dialog .btn .fa { + color: #fff!important +} + +.modal-dialog [class*=btn-outline-] .fa { + color: inherit!important +} + +.modal-dialog.cascading-modal { + margin-top: 10% +} + +.modal-dialog.cascading-modal .close { + color: #fff; + opacity: 1; + text-shadow: none +} + +.modal-dialog.cascading-modal .modal-header { + text-align: center; + margin: -2rem 1rem 1rem; + padding: 1.5rem; + border: none; + border-radius: 3px +} + +.modal-dialog.cascading-modal .modal-header .close { + margin-right: 1rem +} + +.modal-dialog.cascading-modal .modal-header .title { + width: 100%; + margin-bottom: 0; + font-size: 1.25rem +} + +.modal-dialog.cascading-modal .modal-header .title .fa { + margin-right: 9px +} + +.modal-dialog.cascading-modal .modal-header .social-buttons { + margin-top: 1.5rem +} + +.modal-dialog.cascading-modal .modal-header .social-buttons a { + font-size: 1rem +} + +.modal-dialog.cascading-modal .modal-c-tabs .nav-tabs { + margin: -1.5rem 1rem 0 +} + +.modal-dialog.cascading-modal .modal-c-tabs .tab-content { + padding: 1.7rem 0 0 +} + +.modal-dialog.cascading-modal .nav-tabs { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex +} + +.modal-dialog.cascading-modal .nav-tabs li { + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.modal-dialog.cascading-modal .nav-tabs li a { + text-align: center; + font-weight: 400 +} + +.modal-dialog.cascading-modal .modal-body, +.modal-dialog.cascading-modal .modal-footer { + color: #616161; + padding-right: 2rem; + padding-left: 2rem +} + +.modal-dialog.cascading-modal .modal-body .additional-option, +.modal-dialog.cascading-modal .modal-footer .additional-option { + text-align: center; + margin-top: 1rem +} + +.modal-dialog.cascading-modal.modal-avatar { + margin-top: 6rem +} + +.modal-dialog.cascading-modal.modal-avatar .modal-header { + margin: -6rem 2rem -1rem +} + +.modal-dialog.cascading-modal.modal-avatar .modal-header img { + width: 130px; + margin-left: auto; + margin-right: auto +} + +.modal-dialog.modal-notify .heading { + margin: 0; + padding: .3rem; + color: #fff; + font-size: 1.15rem +} + +.modal-dialog.modal-notify .modal-header { + border: 0 +} + +.modal-dialog.modal-notify .close { + opacity: 1 +} + +.modal-dialog.modal-notify .modal-body { + padding: 1.5rem; + color: #616161 +} + +.modal-dialog.modal-notify .btn-outline-secondary-modal { + background-color: transparent +} + +.modal-dialog.modal-notify.modal-info .badge, +.modal-dialog.modal-notify.modal-info .btn-primary-modal, +.modal-dialog.modal-notify.modal-info .modal-header { + background-color: #5394ff +} + +.modal-dialog.modal-notify.modal-info .fa { + color: #5394ff +} + +.modal-dialog.modal-notify.modal-info .btn-primary-modal:hover { + background-color: #6da4ff!important +} + +.modal-dialog.modal-notify.modal-info .btn-primary-modal.active, +.modal-dialog.modal-notify.modal-info .btn-primary-modal:active, +.modal-dialog.modal-notify.modal-info .btn-primary-modal:focus { + background-color: #0764ff!important +} + +.modal-dialog.modal-notify.modal-info .btn-primary-modal.dropdown-toggle { + background-color: #5394ff!important +} + +.modal-dialog.modal-notify.modal-info .btn-primary-modal.dropdown-toggle:focus, +.modal-dialog.modal-notify.modal-info .btn-primary-modal.dropdown-toggle:hover { + background-color: #6da4ff!important +} + +.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal { + border: 2px solid #5394ff; + color: #5394ff!important; + background-color: transparent +} + +.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal.active, +.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal:active, +.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal:active:focus, +.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal:focus, +.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal:hover { + background-color: transparent; + color: #5394ff; + border-color: #5394ff +} + +.modal-dialog.modal-notify.modal-warning .badge, +.modal-dialog.modal-notify.modal-warning .btn-primary-modal, +.modal-dialog.modal-notify.modal-warning .modal-header { + background-color: #ff8e38 +} + +.modal-dialog.modal-notify.modal-warning .fa { + color: #ff8e38 +} + +.modal-dialog.modal-notify.modal-warning .btn-primary-modal:hover { + background-color: #ff9c52!important +} + +.modal-dialog.modal-notify.modal-warning .btn-primary-modal.active, +.modal-dialog.modal-notify.modal-warning .btn-primary-modal:active, +.modal-dialog.modal-notify.modal-warning .btn-primary-modal:focus { + background-color: #eb6500!important +} + +.modal-dialog.modal-notify.modal-warning .btn-primary-modal.dropdown-toggle { + background-color: #ff8e38!important +} + +.modal-dialog.modal-notify.modal-warning .btn-primary-modal.dropdown-toggle:focus, +.modal-dialog.modal-notify.modal-warning .btn-primary-modal.dropdown-toggle:hover { + background-color: #ff9c52!important +} + +.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal { + border: 2px solid #ff8e38; + color: #ff8e38!important; + background-color: transparent +} + +.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal.active, +.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal:active, +.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal:active:focus, +.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal:focus, +.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal:hover { + background-color: transparent; + color: #ff8e38; + border-color: #ff8e38 +} + +.modal-dialog.modal-notify.modal-success .badge, +.modal-dialog.modal-notify.modal-success .btn-primary-modal, +.modal-dialog.modal-notify.modal-success .modal-header { + background-color: #01d36b +} + +.modal-dialog.modal-notify.modal-success .fa { + color: #01d36b +} + +.modal-dialog.modal-notify.modal-success .btn-primary-modal:hover { + background-color: #01ec78!important +} + +.modal-dialog.modal-notify.modal-success .btn-primary-modal.active, +.modal-dialog.modal-notify.modal-success .btn-primary-modal:active, +.modal-dialog.modal-notify.modal-success .btn-primary-modal:focus { + background-color: #018744!important +} + +.modal-dialog.modal-notify.modal-success .btn-primary-modal.dropdown-toggle { + background-color: #01d36b!important +} + +.modal-dialog.modal-notify.modal-success .btn-primary-modal.dropdown-toggle:focus, +.modal-dialog.modal-notify.modal-success .btn-primary-modal.dropdown-toggle:hover { + background-color: #01ec78!important +} + +.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal { + border: 2px solid #01d36b; + color: #01d36b!important; + background-color: transparent +} + +.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal.active, +.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal:active, +.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal:active:focus, +.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal:focus, +.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal:hover { + background-color: transparent; + color: #01d36b; + border-color: #01d36b +} + +.modal-dialog.modal-notify.modal-danger .badge, +.modal-dialog.modal-notify.modal-danger .btn-primary-modal, +.modal-dialog.modal-notify.modal-danger .modal-header { + background-color: #ff4b4b +} + +.modal-dialog.modal-notify.modal-danger .fa { + color: #ff4b4b +} + +.modal-dialog.modal-notify.modal-danger .btn-primary-modal:hover { + background-color: #ff6565!important +} + +.modal-dialog.modal-notify.modal-danger .btn-primary-modal.active, +.modal-dialog.modal-notify.modal-danger .btn-primary-modal:active, +.modal-dialog.modal-notify.modal-danger .btn-primary-modal:focus { + background-color: #fe0000!important +} + +.modal-dialog.modal-notify.modal-danger .btn-primary-modal.dropdown-toggle { + background-color: #ff4b4b!important +} + +.modal-dialog.modal-notify.modal-danger .btn-primary-modal.dropdown-toggle:focus, +.modal-dialog.modal-notify.modal-danger .btn-primary-modal.dropdown-toggle:hover { + background-color: #ff6565!important +} + +.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal { + border: 2px solid #ff4b4b; + color: #ff4b4b!important; + background-color: transparent +} + +.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal.active, +.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal:active, +.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal:active:focus, +.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal:focus, +.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal:hover { + background-color: transparent; + color: #ff4b4b; + border-color: #ff4b4b +} + +.progress.progress-default, +.progress.progress-default .progress-bar { + height: 1rem +} + +.progress.progress-wider, +.progress.progress-wider .progress-bar { + height: 20px +} + +.progress.progress-narrower, +.progress.progress-narrower .progress-bar { + height: 1px +} + +.carousel .carousel-control-next-icon, +.carousel .carousel-control-prev-icon { + width: 36px; + height: 36px +} + +.carousel .carousel-control-prev-icon { + background-image: url(../img//svg/arrow_left.svg) +} + +.carousel .carousel-control-next-icon { + background-image: url(../img//svg/arrow_right.svg) +} + +.carousel .carousel-indicators li { + max-width: 10px; + height: 10px; + border-radius: 50%; + cursor: pointer +} + +.carousel .video-fluid { + height: 100%; + width: 100% +} + +.carousel-fade .carousel-item { + opacity: 0; + -webkit-transition-duration: .6s; + transition-duration: .6s; + -webkit-transition-property: opacity; + transition-property: opacity +} + +.carousel-fade .carousel-item-next.carousel-item-left, +.carousel-fade .carousel-item-prev.carousel-item-right, +.carousel-fade .carousel-item.active { + opacity: 1 +} + +.carousel-fade .active.carousel-item-left, +.carousel-fade .active.carousel-item-right { + opacity: 0 +} + +.carousel-fade .active.carousel-item-left, +.carousel-fade .active.carousel-item-prev, +.carousel-fade .carousel-item-next, +.carousel-fade .carousel-item-prev, +.carousel-fade .carousel-item.active { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0) +} + +@supports (transform-style: preserve-3d) { + .carousel-fade .active.carousel-item-left, + .carousel-fade .active.carousel-item-prev, + .carousel-fade .carousel-item-next, + .carousel-fade .carousel-item-prev, + .carousel-fade .carousel-item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0) + } +} + +.accordion .card { + border-bottom: 1px solid #eee; + -webkit-box-shadow: none; + box-shadow: none +} + +.accordion .card .card-header { + padding: 1rem 1.5rem; + background: 0 0; + border-bottom: 0 +} + +.accordion .card .card-header a:not(.collapsed) .rotate-icon { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg) +} + +.accordion .card .fa-angle-down { + float: right +} + +.accordion .card .card-block { + padding-top: .25rem +} + +.accordion .card .card-body { + line-height: 1.7; + color: #626262; + font-size: .9rem; + font-weight: 300 +} + +.accordion .card h5 { + font-size: 1.1rem; + font-weight: 400 +} + +.collapsible-body { + display: none +} + +.author-box, +.jumbotron { + background-color: #fff; + padding: 2rem +} + +.jumbotron.m-1, +.jumbotron.m-2, +.jumbotron.m-3, +.m-1.author-box, +.m-2.author-box, +.m-3.author-box, +.section-blog-fw .author-box, +.section-blog-fw .jumbotron { + z-index: 50; + position: relative; + margin-left: 3%; + margin-right: 3% +} + +.jumbotron.m-1, +.m-1.author-box, +.section-blog-fw .author-box, +.section-blog-fw .jumbotron { + margin-top: -20px +} + +.jumbotron.m-2, +.m-2.author-box { + margin-top: -30px +} + +.jumbotron.m-3, +.m-3.author-box { + margin-top: -40px +} + +.view { + overflow: hidden; + position: relative; + cursor: default +} + +.view .mask { + background-attachment: fixed +} + +.view .full-bg-img, +.view .mask { + width: 100%; + height: 100%; + position: absolute; + overflow: hidden; + top: 0; + left: 0 +} + +.view img, +.view video { + display: block; + position: relative +} + +.hm-zoom img, +.hm-zoom video, +.overlay img, +.overlay video { + -webkit-transition: all .2s linear; + transition: all .2s linear +} + +.hm-zoom:hover .mask, +.overlay:hover .mask { + opacity: 1 +} + +.hm-zoom:hover img { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1) +} + +.overlay .mask { + opacity: 0; + -webkit-transition: all .4s ease-in-out; + transition: all .4s ease-in-out +} + +.pattern-1 { + background: url(../img/overlays/01.png) +} + +.pattern-2 { + background: url(../img/overlays/02.png) +} + +.pattern-3 { + background: url(../img/overlays/03.png) +} + +.pattern-4 { + background: url(../img/overlays/04.png) +} + +.pattern-5 { + background: url(../img/overlays/05.png) +} + +.pattern-6 { + background: url(../img/overlays/06.png) +} + +.pattern-7 { + background: url(../img/overlays/07.png) +} + +.pattern-8 { + background: url(../img/overlays/08.png) +} + +.pattern-9 { + background: url(../img/overlays/09.png) +} + +.hm-blue-slight .full-bg-img, +.hm-blue-slight .mask { + background-color: rgba(3, 169, 244, .1) +} + +.hm-red-slight .full-bg-img, +.hm-red-slight .mask { + background-color: rgba(244, 67, 54, .1) +} + +.hm-pink-slight .full-bg-img, +.hm-pink-slight .mask { + background-color: rgba(233, 30, 99, .1) +} + +.hm-purple-slight .full-bg-img, +.hm-purple-slight .mask { + background-color: rgba(156, 39, 176, .1) +} + +.hm-indigo-slight .full-bg-img, +.hm-indigo-slight .mask { + background-color: rgba(63, 81, 181, .1) +} + +.hm-cyan-slight .full-bg-img, +.hm-cyan-slight .mask { + background-color: rgba(0, 188, 212, .1) +} + +.hm-teal-slight .full-bg-img, +.hm-teal-slight .mask { + background-color: rgba(0, 150, 136, .1) +} + +.hm-green-slight .full-bg-img, +.hm-green-slight .mask { + background-color: rgba(76, 175, 80, .1) +} + +.hm-lime-slight .full-bg-img, +.hm-lime-slight .mask { + background-color: rgba(205, 220, 57, .1) +} + +.hm-yellow-slight .full-bg-img, +.hm-yellow-slight .mask { + background-color: rgba(255, 235, 59, .1) +} + +.hm-orange-slight .full-bg-img, +.hm-orange-slight .mask { + background-color: rgba(255, 152, 0, .1) +} + +.hm-brown-slight .full-bg-img, +.hm-brown-slight .mask { + background-color: rgba(121, 85, 72, .1) +} + +.hm-grey-slight .full-bg-img, +.hm-grey-slight .mask { + background-color: rgba(158, 158, 158, .1) +} + +.hm-bluegrey-slight .full-bg-img, +.hm-bluegrey-slight .mask { + background-color: rgba(96, 125, 139, .1) +} + +.hm-black-slight .full-bg-img, +.hm-black-slight .mask { + background-color: rgba(0, 0, 0, .1) +} + +.hm-stylish-slight .full-bg-img, +.hm-stylish-slight .mask { + background-color: rgba(62, 69, 81, .1) +} + +.hm-white-slight .full-bg-img, +.hm-white-slight .mask { + background-color: rgba(255, 255, 255, .1) +} + +.hm-blue-light .full-bg-img, +.hm-blue-light .mask { + background-color: rgba(3, 169, 244, .3) +} + +.hm-red-light .full-bg-img, +.hm-red-light .mask { + background-color: rgba(244, 67, 54, .3) +} + +.hm-pink-light .full-bg-img, +.hm-pink-light .mask { + background-color: rgba(233, 30, 99, .3) +} + +.hm-purple-light .full-bg-img, +.hm-purple-light .mask { + background-color: rgba(156, 39, 176, .3) +} + +.hm-indigo-light .full-bg-img, +.hm-indigo-light .mask { + background-color: rgba(63, 81, 181, .3) +} + +.hm-cyan-light .full-bg-img, +.hm-cyan-light .mask { + background-color: rgba(0, 188, 212, .3) +} + +.hm-teal-light .full-bg-img, +.hm-teal-light .mask { + background-color: rgba(0, 150, 136, .3) +} + +.hm-green-light .full-bg-img, +.hm-green-light .mask { + background-color: rgba(76, 175, 80, .3) +} + +.hm-lime-light .full-bg-img, +.hm-lime-light .mask { + background-color: rgba(205, 220, 57, .3) +} + +.hm-yellow-light .full-bg-img, +.hm-yellow-light .mask { + background-color: rgba(255, 235, 59, .3) +} + +.hm-orange-light .full-bg-img, +.hm-orange-light .mask { + background-color: rgba(255, 152, 0, .3) +} + +.hm-brown-light .full-bg-img, +.hm-brown-light .mask { + background-color: rgba(121, 85, 72, .3) +} + +.hm-grey-light .full-bg-img, +.hm-grey-light .mask { + background-color: rgba(158, 158, 158, .3) +} + +.hm-bluegrey-light .full-bg-img, +.hm-bluegrey-light .mask { + background-color: rgba(96, 125, 139, .3) +} + +.hm-black-light .full-bg-img, +.hm-black-light .mask { + background-color: rgba(0, 0, 0, .3) +} + +.hm-stylish-light .full-bg-img, +.hm-stylish-light .mask { + background-color: rgba(62, 69, 81, .3) +} + +.hm-white-light .full-bg-img, +.hm-white-light .mask { + background-color: rgba(255, 255, 255, .3) +} + +.hm-blue-strong .full-bg-img, +.hm-blue-strong .mask { + background-color: rgba(3, 169, 244, .7) +} + +.hm-red-strong .full-bg-img, +.hm-red-strong .mask { + background-color: rgba(244, 67, 54, .7) +} + +.hm-pink-strong .full-bg-img, +.hm-pink-strong .mask { + background-color: rgba(233, 30, 99, .7) +} + +.hm-purple-strong .full-bg-img, +.hm-purple-strong .mask { + background-color: rgba(156, 39, 176, .7) +} + +.hm-indigo-strong .full-bg-img, +.hm-indigo-strong .mask { + background-color: rgba(63, 81, 181, .7) +} + +.hm-cyan-strong .full-bg-img, +.hm-cyan-strong .mask { + background-color: rgba(0, 188, 212, .7) +} + +.hm-teal-strong .full-bg-img, +.hm-teal-strong .mask { + background-color: rgba(0, 150, 136, .7) +} + +.hm-green-strong .full-bg-img, +.hm-green-strong .mask { + background-color: rgba(76, 175, 80, .7) +} + +.hm-lime-strong .full-bg-img, +.hm-lime-strong .mask { + background-color: rgba(205, 220, 57, .7) +} + +.hm-yellow-strong .full-bg-img, +.hm-yellow-strong .mask { + background-color: rgba(255, 235, 59, .7) +} + +.hm-orange-strong .full-bg-img, +.hm-orange-strong .mask { + background-color: rgba(255, 152, 0, .7) +} + +.hm-brown-strong .full-bg-img, +.hm-brown-strong .mask { + background-color: rgba(121, 85, 72, .7) +} + +.hm-grey-strong .full-bg-img, +.hm-grey-strong .mask { + background-color: rgba(158, 158, 158, .7) +} + +.hm-bluegrey-strong .full-bg-img, +.hm-bluegrey-strong .mask { + background-color: rgba(96, 125, 139, .7) +} + +.hm-black-strong .full-bg-img, +.hm-black-strong .mask { + background-color: rgba(0, 0, 0, .7) +} + +.hm-stylish-strong .full-bg-img, +.hm-stylish-strong .mask { + background-color: rgba(62, 69, 81, .7) +} + +.hm-white-strong .full-bg-img, +.hm-white-strong .mask { + background-color: rgba(255, 255, 255, .7) +} + +.full-height, +.full-height body, +.full-height header, +.full-height header .view { + height: 100% +} + +.intro { + min-height: 1000px; + position: relative +} + +@media (max-width: 768px) { + .intro { + min-height: 1000px + } +} + +.intro-video video { + top: 50%; + left: 50%; + min-width: 100%; + min-height: 100%; + width: auto; + height: auto; + z-index: -100; + -webkit-transform: translateX(-50%) translateY(-50%); + -ms-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + background-repeat: no-repeat; + background-size: cover; + background-position: center center; + -webkit-transition: 1s opacity; + transition: 1s opacity +} + +.waves-effect { + position: relative; + cursor: pointer; + overflow: hidden; + user-select: none; + z-index: 1 +} + +.pswp__container, +.pswp__counter, +.pswp__img, +.pswp__share-modal { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none +} + +.waves-effect .waves-ripple { + position: absolute; + border-radius: 50%; + width: 100px; + height: 100px; + margin-top: -50px; + margin-left: -50px; + opacity: 0; + background: rgba(0, 0, 0, .2); + background: -webkit-radial-gradient(rgba(0, 0, 0, .2) 0, rgba(0, 0, 0, .3) 40%, rgba(0, 0, 0, .4) 50%, rgba(0, 0, 0, .5) 60%, rgba(255, 255, 255, 0) 70%); + background: radial-gradient(rgba(0, 0, 0, .2) 0, rgba(0, 0, 0, .3) 40%, rgba(0, 0, 0, .4) 50%, rgba(0, 0, 0, .5) 60%, rgba(255, 255, 255, 0) 70%); + -webkit-transition: all .5s ease-out; + transition: all .5s ease-out; + -webkit-transition-property: opacity, -webkit-transform; + transition-property: opacity, -webkit-transform; + transition-property: transform, opacity; + transition-property: transform, opacity, -webkit-transform; + -webkit-transform: scale(0) translate(0, 0); + -ms-transform: scale(0) translate(0, 0); + transform: scale(0) translate(0, 0); + pointer-events: none +} + +.waves-effect.waves-light .waves-ripple { + background: rgba(255, 255, 255, .4); + background: -webkit-radial-gradient(rgba(255, 255, 255, .2) 0, rgba(255, 255, 255, .3) 40%, rgba(255, 255, 255, .4) 50%, rgba(255, 255, 255, .5) 60%, rgba(255, 255, 255, 0) 70%); + background: radial-gradient(rgba(255, 255, 255, .2) 0, rgba(255, 255, 255, .3) 40%, rgba(255, 255, 255, .4) 50%, rgba(255, 255, 255, .5) 60%, rgba(255, 255, 255, 0) 70%) +} + +.waves-effect.waves-classic .waves-ripple { + background: rgba(0, 0, 0, .2) +} + +.waves-effect.waves-classic.waves-light .waves-ripple { + background: rgba(255, 255, 255, .4) +} + +.waves-notransition { + -webkit-transition: none!important; + transition: none!important +} + +.waves-button, +.waves-circle { + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-mask-image: -webkit-radial-gradient(circle, #fff 100%, #000 100%) +} + +.waves-button, +.waves-button-input, +.waves-button:hover, +.waves-button:visited { + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + border: none; + outline: 0; + color: inherit; + background-color: transparent; + font-size: 1em; + line-height: 1em; + text-align: center; + text-decoration: none; + z-index: 1 +} + +.waves-button { + padding: .85em 1.1em; + border-radius: .2em +} + +.waves-button-input { + margin: 0; + padding: .85em 1.1em +} + +.waves-input-wrapper { + border-radius: .2em; + display: inline-block +} + +.waves-input-wrapper.waves-button { + padding: 0 +} + +.waves-input-wrapper .waves-button-input { + position: relative; + top: 0; + left: 0; + z-index: 1 +} + +.waves-circle { + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50% +} + +.waves-float { + -webkit-mask-image: none; + -webkit-box-shadow: 0 1px 1.5px 1px rgba(0, 0, 0, .12); + box-shadow: 0 1px 1.5px 1px rgba(0, 0, 0, .12); + -webkit-transition: all .3s; + transition: all .3s +} + +.waves-float:active { + -webkit-box-shadow: 0 8px 20px 1px rgba(0, 0, 0, .3); + box-shadow: 0 8px 20px 1px rgba(0, 0, 0, .3) +} + +.waves-block { + display: block +} + +a.waves-effect, +a.waves-light { + display: inline-block +} + +input[type=date], +input[type=datetime-local], +input[type=email], +input[type=number], +input[type=password], +input[type=search-md], +input[type=search], +input[type=tel], +input[type=text], +input[type=time], +input[type=url], +textarea.md-textarea { + background-color: transparent; + border: none; + border-bottom: 1px solid #bdbdbd; + border-radius: 0; + outline: 0; + height: 2.1rem; + width: 100%; + font-size: 1rem; + -webkit-box-shadow: none; + box-shadow: none; + -webkit-box-sizing: content-box; + box-sizing: content-box; + -webkit-transition: all .3s; + transition: all .3s +} + +input[type=date]:disabled, +input[type=date][readonly=readonly], +input[type=datetime-local]:disabled, +input[type=datetime-local][readonly=readonly], +input[type=email]:disabled, +input[type=email][readonly=readonly], +input[type=number]:disabled, +input[type=number][readonly=readonly], +input[type=password]:disabled, +input[type=password][readonly=readonly], +input[type=search-md]:disabled, +input[type=search-md][readonly=readonly], +input[type=search]:disabled, +input[type=search][readonly=readonly], +input[type=tel]:disabled, +input[type=tel][readonly=readonly], +input[type=text]:disabled, +input[type=text][readonly=readonly], +input[type=time]:disabled, +input[type=time][readonly=readonly], +input[type=url]:disabled, +input[type=url][readonly=readonly], +textarea.md-textarea:disabled, +textarea.md-textarea[readonly=readonly] { + color: rgba(0, 0, 0, .46); + border-bottom: 1px dotted rgba(0, 0, 0, .46); + background-color: transparent +} + +input[type=date]:disabled+label, +input[type=date][readonly=readonly]+label, +input[type=datetime-local]:disabled+label, +input[type=datetime-local][readonly=readonly]+label, +input[type=email]:disabled+label, +input[type=email][readonly=readonly]+label, +input[type=number]:disabled+label, +input[type=number][readonly=readonly]+label, +input[type=password]:disabled+label, +input[type=password][readonly=readonly]+label, +input[type=search-md]:disabled+label, +input[type=search-md][readonly=readonly]+label, +input[type=search]:disabled+label, +input[type=search][readonly=readonly]+label, +input[type=tel]:disabled+label, +input[type=tel][readonly=readonly]+label, +input[type=text]:disabled+label, +input[type=text][readonly=readonly]+label, +input[type=time]:disabled+label, +input[type=time][readonly=readonly]+label, +input[type=url]:disabled+label, +input[type=url][readonly=readonly]+label, +textarea.md-textarea:disabled+label, +textarea.md-textarea[readonly=readonly]+label { + color: rgba(0, 0, 0, .46); + background-color: transparent +} + +input[type=date]:focus:not([readonly]), +input[type=datetime-local]:focus:not([readonly]), +input[type=email]:focus:not([readonly]), +input[type=number]:focus:not([readonly]), +input[type=password]:focus:not([readonly]), +input[type=search-md]:focus:not([readonly]), +input[type=search]:focus:not([readonly]), +input[type=tel]:focus:not([readonly]), +input[type=text]:focus:not([readonly]), +input[type=time]:focus:not([readonly]), +input[type=url]:focus:not([readonly]), +textarea.md-textarea:focus:not([readonly]) { + border-bottom: 1px solid #4285F4; + -webkit-box-shadow: 0 1px 0 0 #4285F4; + box-shadow: 0 1px 0 0 #4285F4 +} + +input[type=date]:focus:not([readonly])+label, +input[type=datetime-local]:focus:not([readonly])+label, +input[type=email]:focus:not([readonly])+label, +input[type=number]:focus:not([readonly])+label, +input[type=password]:focus:not([readonly])+label, +input[type=search-md]:focus:not([readonly])+label, +input[type=search]:focus:not([readonly])+label, +input[type=tel]:focus:not([readonly])+label, +input[type=text]:focus:not([readonly])+label, +input[type=time]:focus:not([readonly])+label, +input[type=url]:focus:not([readonly])+label, +textarea.md-textarea:focus:not([readonly])+label { + color: #4285F4 +} + +input[type=date].valid, +input[type=date]:focus.valid, +input[type=datetime-local].valid, +input[type=datetime-local]:focus.valid, +input[type=email].valid, +input[type=email]:focus.valid, +input[type=number].valid, +input[type=number]:focus.valid, +input[type=password].valid, +input[type=password]:focus.valid, +input[type=search-md].valid, +input[type=search-md]:focus.valid, +input[type=search].valid, +input[type=search]:focus.valid, +input[type=tel].valid, +input[type=tel]:focus.valid, +input[type=text].valid, +input[type=text]:focus.valid, +input[type=time].valid, +input[type=time]:focus.valid, +input[type=url].valid, +input[type=url]:focus.valid, +textarea.md-textarea.valid, +textarea.md-textarea:focus.valid { + border-bottom: 1px solid #00C851; + -webkit-box-shadow: 0 1px 0 0 #00C851; + box-shadow: 0 1px 0 0 #00C851 +} + +input[type=date].valid+label:after, +input[type=date]:focus.valid+label:after, +input[type=datetime-local].valid+label:after, +input[type=datetime-local]:focus.valid+label:after, +input[type=email].valid+label:after, +input[type=email]:focus.valid+label:after, +input[type=number].valid+label:after, +input[type=number]:focus.valid+label:after, +input[type=password].valid+label:after, +input[type=password]:focus.valid+label:after, +input[type=search-md].valid+label:after, +input[type=search-md]:focus.valid+label:after, +input[type=search].valid+label:after, +input[type=search]:focus.valid+label:after, +input[type=tel].valid+label:after, +input[type=tel]:focus.valid+label:after, +input[type=text].valid+label:after, +input[type=text]:focus.valid+label:after, +input[type=time].valid+label:after, +input[type=time]:focus.valid+label:after, +input[type=url].valid+label:after, +input[type=url]:focus.valid+label:after, +textarea.md-textarea.valid+label:after, +textarea.md-textarea:focus.valid+label:after { + content: attr(data-success); + color: #00C851; + opacity: 1 +} + +input[type=date].invalid, +input[type=date]:focus.invalid, +input[type=datetime-local].invalid, +input[type=datetime-local]:focus.invalid, +input[type=email].invalid, +input[type=email]:focus.invalid, +input[type=number].invalid, +input[type=number]:focus.invalid, +input[type=password].invalid, +input[type=password]:focus.invalid, +input[type=search-md].invalid, +input[type=search-md]:focus.invalid, +input[type=search].invalid, +input[type=search]:focus.invalid, +input[type=tel].invalid, +input[type=tel]:focus.invalid, +input[type=text].invalid, +input[type=text]:focus.invalid, +input[type=time].invalid, +input[type=time]:focus.invalid, +input[type=url].invalid, +input[type=url]:focus.invalid, +textarea.md-textarea.invalid, +textarea.md-textarea:focus.invalid { + border-bottom: 1px solid #F44336; + -webkit-box-shadow: 0 1px 0 0 #F44336; + box-shadow: 0 1px 0 0 #F44336 +} + +input[type=date].invalid+label:after, +input[type=date]:focus.invalid+label:after, +input[type=datetime-local].invalid+label:after, +input[type=datetime-local]:focus.invalid+label:after, +input[type=email].invalid+label:after, +input[type=email]:focus.invalid+label:after, +input[type=number].invalid+label:after, +input[type=number]:focus.invalid+label:after, +input[type=password].invalid+label:after, +input[type=password]:focus.invalid+label:after, +input[type=search-md].invalid+label:after, +input[type=search-md]:focus.invalid+label:after, +input[type=search].invalid+label:after, +input[type=search]:focus.invalid+label:after, +input[type=tel].invalid+label:after, +input[type=tel]:focus.invalid+label:after, +input[type=text].invalid+label:after, +input[type=text]:focus.invalid+label:after, +input[type=time].invalid+label:after, +input[type=time]:focus.invalid+label:after, +input[type=url].invalid+label:after, +input[type=url]:focus.invalid+label:after, +textarea.md-textarea.invalid+label:after, +textarea.md-textarea:focus.invalid+label:after { + content: attr(data-error); + color: #F44336; + opacity: 1 +} + +input[type=date]+label:after, +input[type=datetime-local]+label:after, +input[type=email]+label:after, +input[type=number]+label:after, +input[type=password]+label:after, +input[type=search-md]+label:after, +input[type=search]+label:after, +input[type=tel]+label:after, +input[type=text]+label:after, +input[type=time]+label:after, +input[type=url]+label:after, +textarea.md-textarea+label:after { + display: block; + content: ""; + position: absolute; + top: 65px; + opacity: 0; + -webkit-transition: .2s opacity ease-out, .2s color ease-out; + transition: .2s opacity ease-out, .2s color ease-out +} + +input[type=date].input-alternate, +input[type=datetime-local].input-alternate, +input[type=email].input-alternate, +input[type=number].input-alternate, +input[type=password].input-alternate, +input[type=search-md].input-alternate, +input[type=search].input-alternate, +input[type=tel].input-alternate, +input[type=text].input-alternate, +input[type=time].input-alternate, +input[type=url].input-alternate, +textarea.md-textarea.input-alternate { + padding: 0 15px; + height: 2.1rem; + -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 2px 1px -1px rgba(0, 0, 0, .12); + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 2px 1px -1px rgba(0, 0, 0, .12); + font-size: .875rem; + border-bottom: 0; + -webkit-transition: none!important; + transition: none!important +} + +input[type=date].input-alternate:focus, +input[type=date].input-alternate:hover, +input[type=datetime-local].input-alternate:focus, +input[type=datetime-local].input-alternate:hover, +input[type=email].input-alternate:focus, +input[type=email].input-alternate:hover, +input[type=number].input-alternate:focus, +input[type=number].input-alternate:hover, +input[type=password].input-alternate:focus, +input[type=password].input-alternate:hover, +input[type=search-md].input-alternate:focus, +input[type=search-md].input-alternate:hover, +input[type=search].input-alternate:focus, +input[type=search].input-alternate:hover, +input[type=tel].input-alternate:focus, +input[type=tel].input-alternate:hover, +input[type=text].input-alternate:focus, +input[type=text].input-alternate:hover, +input[type=time].input-alternate:focus, +input[type=time].input-alternate:hover, +input[type=url].input-alternate:focus, +input[type=url].input-alternate:hover, +textarea.md-textarea.input-alternate:focus, +textarea.md-textarea.input-alternate:hover { + -webkit-box-shadow: 0 3px 8px 0 rgba(0, 0, 0, .2), 0 0 0 1px rgba(0, 0, 0, .08)!important; + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, .2), 0 0 0 1px rgba(0, 0, 0, .08)!important; + border-bottom: 0 +} + +.form-control { + padding: .5rem 0 .6rem; + font-size: 1rem; + line-height: 1.5; + background-color: transparent; + background-image: none; + border-radius: 0; + margin-top: .2rem; + margin-bottom: 1rem +} + +.md-form, +.md-form .btn { + margin-bottom: 1.5rem +} + +.form-control:focus { + background: 0 0; + -webkit-box-shadow: none; + box-shadow: none +} + +.form-control:disabled, +.form-control[readonly] { + background-color: transparent; + border-bottom: 1px solid #bdbdbd +} + +.md-form { + position: relative +} + +.md-form label { + -webkit-transition: .2s ease-out; + transition: .2s ease-out; + color: #757575; + position: absolute; + top: .8rem; + left: 0; + font-size: 1rem; + cursor: text +} + +.btn-floating, +.card .card-reveal .card-title, +.card-wrapper .back .card-title { + cursor: pointer +} + +.md-form label.active { + -webkit-transform: translateY(-140%); + -ms-transform: translateY(-140%); + transform: translateY(-140%); + font-size: .8rem +} + +.md-form .prefix { + -webkit-transition: color .2s; + transition: color .2s; + position: absolute; + width: 3rem; + font-size: 2rem; + padding-top: .5rem +} + +.btn-flat, +.btn-floating { + position: relative; + margin: 10px +} + +.md-form .prefix~input, +.md-form .prefix~textarea { + margin-left: 3rem; + width: 92%; + width: -webkit-calc(100% - 3rem); + width: calc(100% - 3rem) +} + +.md-form .prefix~label { + margin-left: 3rem +} + +.md-form .prefix.active { + color: #4285F4 +} + +@media only screen and (max-width: 992px) { + .md-form .prefix~input { + width: 86%; + width: -webkit-calc(100% - 3rem); + width: calc(100% - 3rem) + } +} + +@media only screen and (max-width: 600px) { + .md-form .prefix~input { + width: 80%; + width: -webkit-calc(100% - 3rem); + width: calc(100% - 3rem) + } +} + +.md-form.form-sm input { + padding-bottom: .2rem; + padding-top: .2rem; + font-size: .8rem; + line-height: .5 +} + +.md-form.form-sm label { + font-size: .9rem +} + +.md-form.form-sm .prefix { + font-size: 1.5rem; + top: .4rem +} + +.md-form.form-sm .prefix~input, +.md-form.form-sm .prefix~label, +.md-form.form-sm .prefix~textarea { + margin-left: 2.2rem +} + +.md-form.input-group { + padding-left: 1rem +} + +.md-form.input-group:-moz-placeholder { + color: #999; + padding-top: 2px +} + +.md-form.input-group::-ms-placeholder { + color: #999; + padding-top: 2px +} + +.md-form.input-group::-webkit-input-placeholder { + color: #999; + padding-top: 2px +} + +.md-form.input-group::-moz-placeholder { + color: #999; + padding-top: 2px +} + +.md-form.input-group:-ms-input-placeholder { + color: #999; + padding-top: 2px +} + +.md-form.input-group::placeholder { + color: #999; + padding-top: 2px +} + +.form-group { + display: block +} + +.form-inline fieldset { + margin-right: 1.5rem +} + +.form-inline .form-group { + margin-right: 2rem +} + +textarea { + width: 100%; + height: 3rem; + background-color: transparent +} + +textarea.md-textarea { + overflow-y: hidden; + padding: 1.6rem 0; + resize: none; + min-height: 3rem +} + +.hiddendiv { + display: none; + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; + padding-top: 1.2rem +} + +.orange-gradient { + background: -webkit-linear-gradient(50deg, #FFD86F, #FC6262); + background: linear-gradient(40deg, #FFD86F, #FC6262) +} + +.table-inverse td, +.table-inverse th, +.table-inverse thead th { + border-color: #fff +} + +.edge-header { + display: block; + height: 278px; + background-color: #ccc +} + +.free-bird { + margin-top: -100px +} + +footer.page-footer { + margin-top: 20px; + padding-top: 20px; + color: #fff +} + +footer.page-footer .container-fluid { + width: auto +} + +footer.page-footer .footer-copyright { + overflow: hidden; + height: 50px; + line-height: 50px; + color: rgba(255, 255, 255, .6); + background-color: rgba(0, 0, 0, .2); + text-align: center; + font-size: .9rem +} + +footer.page-footer a { + color: #fff +} + +footer.page-footer .call-to-action { + text-align: center; + padding-top: 1.3rem; + padding-bottom: .5rem +} + +footer.page-footer .call-to-action ul li { + display: inline-block; + padding-right: 10px +} + +footer.page-footer .social-section ul li { + display: inline-block +} + +footer.page-footer .social-section ul a { + margin-left: 0; + padding-left: 0 +} + +footer.page-footer ul, +ul.instagram-photos { + list-style-type: none; + padding: 0 +} + +ul.instagram-photos li { + display: inline-block; + max-width: 100px; + margin: 4px +} + +ul.instagram-photos li img { + margin: 0 +} + +.media .media-left { + padding: 0 10px 10px 0 +} + +.list-group a:hover { + -webkit-transition: .5s; + transition: .5s +} + +table th { + font-size: .9rem; + font-weight: 400 +} + +table td { + font-size: .9rem; + font-weight: 300 +} + +.card-inverse h3, +.card.card-cascade .view.gradient-card-header h2, +.social-list { + font-weight: 400 +} + +table.table thead th { + border-top: none +} + +table.table td, +table.table th { + padding-top: 1.1rem; + padding-bottom: 1rem +} + +table.table a { + margin: 0; + color: #212529 +} + +table.table .label-table { + margin: 0; + padding: 0; + line-height: 15px; + height: 15px +} + +table.table .btn-table { + margin: 0 1px; + padding: 3px 7px +} + +.colorful-side-nav .collapsible a, +.stylish-side-nav .collapsible a { + margin: 0 +} + +table.table .btn-table .fa { + font-size: 11px +} + +table.table-hover tbody tr:hover { + background-color: rgba(0, 0, 0, .075); + -webkit-transition: .5s; + transition: .5s +} + +table .th-lg { + min-width: 9rem +} + +table.table-sm td, +table.table-sm th { + padding-top: .6rem; + padding-bottom: .6rem +} + +.colorful-side-nav .collapsible>li, +.stylish-side-nav .collapsible>li { + padding: 0 +} + +.btn-mdb { + background-color: #45526E +} + +.btn-mdb:hover { + background-color: #4f5e7e!important +} + +.btn-mdb.active, +.btn-mdb:active, +.btn-mdb:focus { + background-color: #282f3f!important +} + +.btn-mdb.dropdown-toggle { + background-color: #45526E!important +} + +.btn-mdb.dropdown-toggle:focus, +.btn-mdb.dropdown-toggle:hover { + background-color: #4f5e7e!important +} + +.colorful-side-nav, +.colorful-side-nav li { + background-color: #00695c +} + +.colorful-side-nav .collapsible a.active, +.colorful-side-nav .collapsible a:active, +.colorful-side-nav li.active, +.colorful-side-nav li:hover { + background-color: #008372 +} + +.colorful-side-nav .social { + border-top: 1px solid #26a69a; + border-bottom: 1px solid #26a69a +} + +.stylish-side-nav, +.stylish-side-nav li { + background-color: #3E4551 +} + +.stylish-side-nav .collapsible a.active, +.stylish-side-nav .collapsible a:active, +.stylish-side-nav li.active, +.stylish-side-nav li:hover { + background-color: #4B515D +} + +.stylish-side-nav .social { + border-top: 1px solid #4B515D; + border-bottom: 1px solid #4B515D +} + +.light-side-nav .logo-wrapper, +.light-side-nav .logo-wrapper a { + height: 80px +} + +.light-side-nav .logo-wrapper img { + padding: 7% 50px +} + +.light-side-nav .collapsible a, +.light-side-nav p { + color: #1C2331 +} + +.light-side-nav .social { + border-top: 1px solid #eee; + border-bottom: 1px solid #eee +} + +.light-side-nav .navbar-form { + margin: 10px +} + +.dark-side-nav, +.dark-side-nav li { + background-color: #212121 +} + +.dark-side-nav .collapsible a .active, +.dark-side-nav .collapsible a:active, +.dark-side-nav li.active, +.dark-side-nav li:hover { + background-color: #2E2E2E +} + +.dark-side-nav .collapsible a { + margin: 0 +} + +.dark-side-nav .collapsible>li { + padding: 0 +} + +.dark-side-nav .social { + border-top: 1px solid #4B515D; + border-bottom: 1px solid #4B515D +} + +.social-list { + width: auto; + padding: 1rem; + list-style-type: none +} + +.social-list li { + margin-top: 15px +} + +.social-list .fa { + margin-right: 20px; + font-size: 20px +} + +.social-list .fa-facebook { + margin-right: 26px +} + +.social-list a { + font-size: 20px +} + +.btn-flat { + padding: 8px 30px; + border: none; + text-decoration: none; + outline: 0!important +} + +.btn.btn-flat { + color: inherit!important; + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none +} + +.btn-floating, +.btn-floating i { + display: inline-block; + color: #fff +} + +.btn-floating { + z-index: 1; + overflow: hidden; + width: 47px; + height: 47px; + padding: 0; + border-radius: 50%; + background-color: #a6c; + -webkit-transition: .3s; + transition: .3s +} + +.btn-floating i { + width: inherit; + font-size: 1.25rem; + line-height: 47px; + text-align: center +} + +.btn-floating:before { + border-radius: 0 +} + +.btn-floating.btn-sm, +.btn-floating.btn-small, +.btn-floating.wishlist { + width: 36.15px; + height: 36.15px +} + +.btn-floating.btn-sm i, +.btn-floating.btn-small i, +.btn-floating.wishlist i { + font-size: .96154rem; + line-height: 36.15px +} + +.btn-floating.btn-large, +.btn-floating.btn-lg { + width: 61.1px; + height: 61.1px +} + +.btn-floating.btn-large i, +.btn-floating.btn-lg i { + font-size: 1.625rem; + line-height: 61.1px +} + +.fixed-action-btn { + position: fixed; + z-index: 998; + right: 35px; + bottom: 35px; + padding-top: 15px; + margin-bottom: 0 +} + +.fixed-action-btn ul { + position: absolute; + right: 0; + bottom: 64px; + left: 0; + margin: 0; + padding: 0; + list-style-type: none; + text-align: center +} + +.fixed-action-btn ul li { + margin-bottom: 15px +} + +.fixed-action-btn ul a.btn-floating { + opacity: 0 +} + +.btn-rounded { + border-radius: 10em +} + +.btn.purple-gradient { + background: -webkit-linear-gradient(50deg, #ff6ec4, #7873f5)!important; + background: linear-gradient(40deg, #ff6ec4, #7873f5)!important; + -webkit-transition: .5s ease; + transition: .5s ease +} + +.btn.purple-gradient:active, +.btn.purple-gradient:active:focus .btn.purple-gradient.active, +.btn.purple-gradient:focus, +.btn.purple-gradient:hover { + background: -webkit-linear-gradient(50deg, #ff88ce, #8f8bf7); + background: linear-gradient(40deg, #ff88ce, #8f8bf7) +} + +.btn.peach-gradient { + background: -webkit-linear-gradient(50deg, #FFD86F, #FC6262)!important; + background: linear-gradient(40deg, #FFD86F, #FC6262)!important; + -webkit-transition: .5s ease; + transition: .5s ease +} + +.btn.peach-gradient:active, +.btn.peach-gradient:active:focus .btn.peach-gradient.active, +.btn.peach-gradient:focus, +.btn.peach-gradient:hover { + background: -webkit-linear-gradient(50deg, #ffdf89, #fc7b7b); + background: linear-gradient(40deg, #ffdf89, #fc7b7b) +} + +.btn.aqua-gradient { + background: -webkit-linear-gradient(50deg, #2096ff, #05ffa3)!important; + background: linear-gradient(40deg, #2096ff, #05ffa3)!important; + -webkit-transition: .5s ease; + transition: .5s ease +} + +.btn.aqua-gradient:active, +.btn.aqua-gradient:active:focus .btn.aqua-gradient.active, +.btn.aqua-gradient:focus, +.btn.aqua-gradient:hover { + background: -webkit-linear-gradient(50deg, #3aa2ff, #1fffac); + background: linear-gradient(40deg, #3aa2ff, #1fffac) +} + +.btn.blue-gradient { + background: -webkit-linear-gradient(50deg, #45cafc, #303f9f)!important; + background: linear-gradient(40deg, #45cafc, #303f9f)!important; + -webkit-transition: .5s ease; + transition: .5s ease +} + +.btn.blue-gradient:active, +.btn.blue-gradient:active:focus .btn.blue-gradient.active, +.btn.blue-gradient:focus, +.btn.blue-gradient:hover { + background: -webkit-linear-gradient(50deg, #5ed1fc, #3647b3); + background: linear-gradient(40deg, #5ed1fc, #3647b3) +} + +.btn-fb { + background-color: #3B5998 +} + +.btn-fb:focus, +.btn-fb:hover { + background-color: #4264aa +} + +.fb-ic { + color: #3B5998!important +} + +.fb-ic:focus, +.fb-ic:hover { + color: #3B5998 +} + +.btn-tw { + background-color: #55ACEE +} + +.btn-tw:focus, +.btn-tw:hover { + background-color: #6cb7f0 +} + +.tw-ic { + color: #55ACEE!important +} + +.tw-ic:focus, +.tw-ic:hover { + color: #55ACEE +} + +.btn-gplus { + background-color: #DD4B39 +} + +.btn-gplus:focus, +.btn-gplus:hover { + background-color: #e15f4f +} + +.gplus-ic { + color: #DD4B39!important +} + +.gplus-ic:focus, +.gplus-ic:hover { + color: #DD4B39 +} + +.btn-yt { + background-color: #ED302F +} + +.btn-yt:focus, +.btn-yt:hover { + background-color: #ef4746 +} + +.yt-ic { + color: #ED302F!important +} + +.yt-ic:focus, +.yt-ic:hover { + color: #ED302F +} + +.btn-li { + background-color: #0082CA +} + +.btn-li:focus, +.btn-li:hover { + background-color: #0092e4 +} + +.li-ic { + color: #0082CA!important +} + +.li-ic:focus, +.li-ic:hover { + color: #0082CA +} + +.btn-pin { + background-color: #C61118 +} + +.btn-pin:focus, +.btn-pin:hover { + background-color: #dd131b +} + +.pin-ic { + color: #C61118!important +} + +.pin-ic:focus, +.pin-ic:hover { + color: #C61118 +} + +.btn-ins { + background-color: #2E5E86 +} + +.btn-ins:focus, +.btn-ins:hover { + background-color: #356b99 +} + +.ins-ic { + color: #2E5E86!important +} + +.ins-ic:focus, +.ins-ic:hover { + color: #2E5E86 +} + +.btn-git { + background-color: #333 +} + +.btn-git:focus, +.btn-git:hover { + background-color: #404040 +} + +.git-ic { + color: #333!important +} + +.git-ic:focus, +.git-ic:hover { + color: #333 +} + +.btn-comm { + background-color: #30CFC0 +} + +.btn-comm:focus, +.btn-comm:hover { + background-color: #45d4c6 +} + +.comm-ic { + color: #30CFC0!important +} + +.comm-ic:focus, +.comm-ic:hover { + color: #30CFC0 +} + +.btn-vk { + background-color: #4C75A3 +} + +.btn-vk:focus, +.btn-vk:hover { + background-color: #5882b1 +} + +.vk-ic { + color: #4C75A3!important +} + +.vk-ic:focus, +.vk-ic:hover { + color: #4C75A3 +} + +.btn-dribbble { + background-color: #EC4A89 +} + +.btn-dribbble:focus, +.btn-dribbble:hover { + background-color: #ee6198 +} + +.dribbble-ic { + color: #EC4A89!important +} + +.dribbble-ic:focus, +.dribbble-ic:hover { + color: #EC4A89 +} + +.btn-so { + background-color: #ffac44 +} + +.btn-so:focus, +.btn-so:hover { + background-color: #ffb75e +} + +.so-ic { + color: #ffac44!important +} + +.so-ic:focus, +.so-ic:hover { + color: #ffac44 +} + +.btn-slack { + background-color: #56b68b +} + +.btn-slack:focus, +.btn-slack:hover { + background-color: #68be97 +} + +.slack-ic { + color: #56b68b!important +} + +.slack-ic:focus, +.slack-ic:hover { + color: #56b68b +} + +.btn-email { + background-color: #4B515D +} + +.btn-email:focus, +.btn-email:hover { + background-color: #565d6b +} + +.email-ic { + color: #4B515D!important +} + +.email-ic:focus, +.email-ic:hover { + color: #4B515D +} + +.btn-social-all { + background-color: #436281 +} + +.btn-social-all:focus, +.btn-social-all:hover { + background-color: #5c7fa3 +} + +.btn-social-all i.fa { + margin-top: 0 +} + +.counter { + position: absolute; + margin-left: -23px; + margin-top: -1px; + background-color: #fe1212; + color: #fff; + padding: 1px 7px; + font-size: 11px; + z-index: 2; + border-radius: 10rem +} + +.social-counters .btn { + margin-left: 9px +} + +.icons-sm { + padding: .5rem; + margin: .5rem; + font-size: 1.2rem +} + +.nav-tabs { + border: 0; + padding: .7rem; + margin-left: 1rem; + margin-right: 1rem; + margin-bottom: -20px; + background-color: #2BBBAD; + z-index: 2; + position: relative; + border-radius: 2px +} + +.nav-tabs .nav-item+.nav-item { + margin-left: 0 +} + +.nav-tabs .nav-link { + border: 0; + color: #fff +} + +.nav-tabs .nav-item.open .nav-link, +.nav-tabs .nav-link.active { + background-color: rgba(255, 255, 255, .2); + color: #fff; + -webkit-transition: all 1s; + transition: all 1s; + border-radius: 2px +} + +.nav-tabs .nav-item.show .nav-link, +.nav-tabs .nav-link.dropdown-toggle { + background-color: #2BBBAD; + color: #fff; + -webkit-transition: all 1s; + transition: all 1s; + border-radius: 2px +} + +.md-pills { + border: 0 +} + +.md-pills li { + padding: .6rem +} + +.md-pills .nav-link { + -webkit-transition: all .4s; + transition: all .4s; + border-radius: 2px; + color: #666; + text-align: center +} + +.md-pills .nav-link:hover { + background-color: rgba(158, 158, 158, .3) +} + +.md-pills .nav-link.active { + color: #fff; + background-color: #2BBBAD +} + +.pills-primary .nav-item .nav-link.active, +.tabs-primary { + background-color: #4285F4 +} + +.pills-danger .nav-item .nav-link.active, +.tabs-danger { + background-color: #ff3547 +} + +.pills-warning .nav-item .nav-link.active, +.tabs-warning { + background-color: #F80 +} + +.pills-success .nav-item .nav-link.active, +.tabs-success { + background-color: #00C851 +} + +.pills-info .nav-item .nav-link.active, +.tabs-info { + background-color: #33b5e5 +} + +.pills-default .nav-item .nav-link.active, +.tabs-default { + background-color: #2BBBAD +} + +.pills-secondary .nav-item .nav-link.active, +.tabs-secondary { + background-color: #a6c +} + +.pills-elegant .nav-item .nav-link.active, +.tabs-elegant { + background-color: #2E2E2E +} + +.pills-unique .nav-item .nav-link.active, +.tabs-unique { + background-color: #880e4f +} + +.pills-dark-green .nav-item .nav-link.active, +.tabs-dark-green { + background-color: #388E3C +} + +.pills-mdb-color .nav-item .nav-link.active, +.tabs-mdb-color { + background-color: #59698D +} + +.pills-red .nav-item .nav-link.active, +.tabs-red { + background-color: #D32F2F +} + +.pills-pink .nav-item .nav-link.active, +.tabs-pink { + background-color: #ec407a +} + +.pills-purple .nav-item .nav-link.active, +.tabs-purple { + background-color: #8e24aa +} + +.pills-deep-purple .nav-item .nav-link.active, +.tabs-deep-purple { + background-color: #512da8 +} + +.pills-indigo .nav-item .nav-link.active, +.tabs-indigo { + background-color: #3f51b5 +} + +.pills-blue .nav-item .nav-link.active, +.tabs-blue { + background-color: #1976D2 +} + +.pills-light-blue .nav-item .nav-link.active, +.tabs-light-blue { + background-color: #82B1FF +} + +.pills-cyan .nav-item .nav-link.active, +.tabs-cyan { + background-color: #00bcd4 +} + +.pills-teal .nav-item .nav-link.active, +.tabs-teal { + background-color: #00796b +} + +.pills-green .nav-item .nav-link.active, +.tabs-green { + background-color: #388E3C +} + +.pills-light-green .nav-item .nav-link.active, +.tabs-light-green { + background-color: #8bc34a +} + +.pills-lime .nav-item .nav-link.active, +.tabs-lime { + background-color: #afb42b +} + +.pills-yellow .nav-item .nav-link.active, +.tabs-yellow { + background-color: #fbc02d +} + +.pills-amber .nav-item .nav-link.active, +.tabs-amber { + background-color: #ffa000 +} + +.pills-orange .nav-item .nav-link.active, +.tabs-orange { + background-color: #f57c00 +} + +.pills-deep-orange .nav-item .nav-link.active, +.tabs-deep-orange { + background-color: #ff7043 +} + +.pills-brown .nav-item .nav-link.active, +.tabs-brown { + background-color: #795548 +} + +.pills-grey .nav-item .nav-link.active, +.tabs-grey { + background-color: #616161 +} + +.pills-blue-grey .nav-item .nav-link.active, +.tabs-blue-grey { + background-color: #78909c +} + +.pills-white .nav-item .nav-link.active, +.tabs-white { + background-color: #fff +} + +.pills-black .nav-item .nav-link.active, +.tabs-black { + background-color: #000 +} + +.tab-content { + padding: 2rem 1rem 1rem; + z-index: 1; + border-radius: 0 0 .3rem .3rem +} + +.tab-content.vertical { + padding-top: 0 +} + +.classic-tabs { + display: -webkit-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + white-space: nowrap; + overflow-x: auto; + border-radius: .3rem .3rem 0 0 +} + +@media (min-width: 62rem) { + .classic-tabs { + overflow-x: hidden + } +} + +.classic-tabs li { + -webkit-box-flex: 1 0 30%; + -webkit-flex: 1 0 30%; + -ms-flex: 1 0 30%; + flex: 1 0 30% +} + +.classic-tabs li a { + display: block; + padding: 20px 24px; + font-size: 13px; + color: rgba(255, 255, 255, .7); + text-align: center; + border-radius: 0 +} + +.card .card-data ul li, +.card .card-review ul li { + display: inline +} + +.classic-tabs li a.active { + border-bottom: 3px solid; + color: #fff +} + +@media (min-width: 62em) { + .classic-tabs li { + -webkit-box-flex: inherit; + -webkit-flex: inherit; + -ms-flex: inherit; + flex: inherit + } + .classic-tabs li:first-child { + margin-left: 56px + } +} + +.classic-tabs.tabs-cyan li a.active { + border-color: #ffeb3b +} + +.classic-tabs.tabs-orange li a.active { + border-color: #E53935 +} + +.classic-tabs.tabs-grey li a.active { + border-color: #FFF +} + +.classic-tabs.tabs-pink li a.active { + border-color: #673ab7 +} + +.classic-tabs.tabs-green li a.active { + border-color: #1565C0 +} + +.classic-tabs.tabs-primary li a.active { + border-color: #FFF +} + +.card.card-image { + background-size: cover; + background-position: center; + width: 100% +} + +.card .card-data { + background-color: #929FBA; + color: #fff; + text-align: center; + height: auto; + padding: 10px +} + +.card .card-data ul { + margin-bottom: 0; + font-size: .9rem +} + +.card .card-data ul li .fa-clock-o { + margin-left: 10px +} + +.card .card-data ul a { + color: #fff +} + +.card .card-data ul a .fa { + margin-left: 5px; + margin-right: 3px +} + +.card.card-dark .card-body { + background-color: #2E2E2E +} + +.card.card-dark .card-body hr { + background-color: #666 +} + +.card.card-cascade { + width: 100% +} + +.card.card-cascade .view { + border-radius: 4px +} + +.card.card-cascade .view.gradient-card-header { + padding: 1.6rem 1rem; + text-align: center +} + +.card.card-cascade .view.gradient-card-header .btn-floating { + background-color: rgba(255, 255, 255, .2) +} + +.card.card-cascade.narrower { + margin-top: 20px +} + +.card.card-cascade.narrower .view { + margin-left: 4%; + margin-right: 4%; + margin-top: -20px +} + +.card.card-cascade.wider { + background-color: transparent +} + +.card.card-cascade.wider .view { + z-index: 2 +} + +.card.card-cascade.wider .card-body { + margin-left: 4%; + margin-right: 4%; + background: #fff; + z-index: 1; + border-radius: 0 0 .3rem .3rem +} + +.card.card-cascade.wider.reverse .card-body { + z-index: 3; + margin-top: -1rem; + border-radius: 4px +} + +.card.card-cascade.card-avatar { + margin-top: 6rem; + text-align: center +} + +.card.card-cascade.card-avatar img { + margin-top: -5rem; + margin-left: auto; + margin-right: auto; + width: 160px; + border-radius: 50% +} + +.card.card-cascade .card-body { + padding-top: 1.8rem +} + +.card.card-cascade.panel-cascade .view { + text-align: center; + color: #fff +} + +.card.card-cascade.panel-cascade .list-group .list-group-item { + margin-bottom: 0; + border: 0; + border-bottom: 1px solid #eee; + color: #495057 +} + +.card.card-cascade.panel-cascade .list-group .list-group-item:hover { + background-color: #eee +} + +.card .activator { + position: absolute; + top: 0; + right: 0; + padding: 1rem; + margin-right: 10px; + font-size: 1.2rem +} + +.card .rating { + color: #ffa000 +} + +.card .btn-action { + margin: -23px 20px -23px auto; + background-color: #929FBA; + height: 47px; + width: 47px; + line-height: 0 +} + +.card .btn-action .fa { + font-size: 18px +} + +.card .btn-action .fa.fa-chevron-right { + margin-top: 2px; + margin-left: 2px +} + +.card .card-review { + margin-top: -1px; + color: #fff; + padding: 50px 20px 20px +} + +.card .card-review ul { + margin-bottom: 0; + font-size: .9rem +} + +.card .card-review ul a { + color: #fff +} + +.card .card-review ul a .fa { + margin-left: 5px; + margin-right: 3px +} + +.card .card-reveal { + position: absolute; + width: 100%; + overflow-y: auto; + top: 100%; + height: 100%; + z-index: 1; + display: none; + padding: 1rem +} + +.card .card-reveal .card-title i { + color: #9e9e9e; + position: absolute; + right: 10px +} + +.card .card-reveal .content, +.card .card-share { + position: relative +} + +.card .card-reveal .content h4 { + margin-top: 20px; + margin-bottom: 15px +} + +.card .card-reveal .content h5 { + margin-top: 30px +} + +.card .card-share .social-reveal { + position: absolute; + top: -28px; + right: 30px; + visibility: hidden; + width: auto; + -webkit-transform: translateZ(0); + transform: translateZ(0); + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + -webkit-transition: -webkit-transform .35s ease; + transition: -webkit-transform .35s ease; + transition: transform .35s ease; + transition: transform .35s ease, -webkit-transform .35s ease +} + +.card .card-share .social-reveal .btn-floating { + margin: .3rem +} + +.card .card-share .social-reveal .btn-floating i { + font-size: 18px +} + +.card .card-share .social-reveal-active { + z-index: 11; + visibility: visible; + -webkit-transform: translateZ(0); + transform: translateZ(0); + -webkit-transform: translateX(-48px); + -ms-transform: translateX(-48px); + transform: translateX(-48px); + -webkit-transition: -webkit-transform .35s ease; + transition: -webkit-transform .35s ease; + transition: transform .35s ease; + transition: transform .35s ease, -webkit-transform .35s ease +} + +.pswp--touch .pswp__button--arrow--left, +.pswp--touch .pswp__button--arrow--right, +.pswp__caption--fake { + visibility: hidden +} + +.card.ovf-hidden { + overflow: hidden +} + +.card .card-footer { + background-color: transparent +} + +.card .card-footer .left { + float: left +} + +.card .card-footer .left .discount { + text-decoration: line-through; + color: #9e9e9e; + font-size: 1.1rem +} + +.card .card-footer .right { + float: right; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex +} + +.card .card-footer .right a { + color: #757575; + margin-left: 1rem; + -webkit-transition: .4s; + transition: .4s +} + +.card .card-footer .right a:hover { + color: #d50000; + -webkit-transition: .4s; + transition: .4s +} + +.card .card-footer .right a.active { + color: #d50000 +} + +.card-wrapper { + margin: 0; + min-height: 500px; + position: relative; + -webkit-perspective: 800px; + perspective: 800px +} + +.card-wrapper .face { + position: absolute; + width: 100%; + height: 100% +} + +.card-wrapper .face h4 { + margin-bottom: 15px +} + +.card-wrapper .face h5 { + margin-top: 30px +} + +.card-wrapper .face .content { + text-align: left; + padding: 15px +} + +.card-wrapper .face .content p { + margin-bottom: 30px +} + +.card-wrapper .face .content .rotate-btn { + padding: 1rem; + margin-right: -8px; + float: right; + font-size: 1.2rem +} + +.card-wrapper .card-up { + overflow: hidden; + height: 50% +} + +.card-wrapper .card-up img { + min-width: 400px +} + +.card-wrapper .avatar { + border-radius: 50%; + display: block; + height: 120px; + margin: -65px auto 0; + overflow: hidden; + width: 120px +} + +.card-wrapper .avatar img { + border: 5px solid #fff; + background: #FFF; + width: 100% +} + +.card-wrapper .card-rotating { + text-align: center; + position: absolute; + width: 100%; + height: 100%; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d +} + +.card-wrapper .card-rotating .content { + position: relative +} + +.card-wrapper .card-rotating .content .rotate-btn { + position: absolute; + right: 8px; + top: 0 +} + +.card-wrapper .fa-repeat, +.card-wrapper .fa-undo { + font-size: 20px; + margin-top: 30px +} + +.card-wrapper .fa-undo { + margin-top: 30px +} + +.card-wrapper .back, +.card-wrapper .front { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transition: -webkit-transform 1s; + transition: -webkit-transform 1s; + transition: transform 1s; + transition: transform 1s, -webkit-transform 1s +} + +.card-wrapper .back { + -webkit-transform: rotateY(-180deg); + transform: rotateY(-180deg); + padding: 1rem +} + +.card-wrapper .back .card-title i { + color: #9e9e9e; + position: absolute; + right: 20px +} + +.card-wrapper .card-rotating.effect__click.flipped .front { + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg) +} + +.card-wrapper .card-rotating.effect__click.flipped .back { + -webkit-transform: rotateY(0); + transform: rotateY(0) +} + +.testimonial-card .card-up { + overflow: hidden; + height: 120px; + border-radius: .3rem .3rem 0 0 +} + +.testimonial-card .avatar { + border-radius: 50%; + height: 120px; + width: 120px; + margin: -65px auto 0; + overflow: hidden; + border: 5px solid #fff +} + +.testimonial-card .avatar img { + width: 100% +} + +.testimonial-card .card-body { + text-align: center +} + +.card-inverse h5 { + font-size: 1rem +} + +.card-overlay { + background-size: cover; + padding: 1.5rem; + border-radius: 2px +} + +.card-overlay p { + margin-bottom: 1rem +} + +.dropdown .dropdown-menu { + padding: .5rem +} + +.dropdown .dropdown-menu.dropdown-primary .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-primary .dropdown-item:hover { + background-color: #4285F4 +} + +.dropdown .dropdown-menu.dropdown-danger .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-danger .dropdown-item:hover { + background-color: #C00 +} + +.dropdown .dropdown-menu.dropdown-default .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-default .dropdown-item:hover { + background-color: #2BBBAD +} + +.dropdown .dropdown-menu.dropdown-secondary .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-secondary .dropdown-item:hover { + background-color: #a6c +} + +.dropdown .dropdown-menu.dropdown-success .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-success .dropdown-item:hover { + background-color: #00C851 +} + +.dropdown .dropdown-menu.dropdown-info .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-info .dropdown-item:hover { + background-color: #33b5e5 +} + +.dropdown .dropdown-menu.dropdown-warning .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-warning .dropdown-item:hover { + background-color: #fb3 +} + +.dropdown .dropdown-menu.dropdown-dark .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-dark .dropdown-item:hover { + background-color: #2E2E2E +} + +.dropdown .dropdown-menu.dropdown-ins .dropdown-item:active, +.dropdown .dropdown-menu.dropdown-ins .dropdown-item:hover { + background-color: #2E5E86 +} + +.dropdown .dropdown-menu .dropdown-item { + padding: .5rem; + margin-left: 0; + font-size: .9rem +} + +.dropdown .dropdown-menu .dropdown-item.disabled { + color: #868e96 +} + +.dropdown .dropdown-menu .dropdown-item.disabled:active, +.dropdown .dropdown-menu .dropdown-item.disabled:focus, +.dropdown .dropdown-menu .dropdown-item.disabled:hover { + -webkit-box-shadow: none; + box-shadow: none; + color: #868e96!important; + background-color: transparent!important +} + +.dropdown .dropdown-menu .dropdown-item:active, +.dropdown .dropdown-menu .dropdown-item:hover { + border-radius: 2px; + -webkit-transition: all .1s linear; + transition: all .1s linear; + background-color: #4285F4 +} + +.dropdown-content { + background-color: #fff; + margin: 0; + display: none; + min-width: 100px; + max-height: 650px; + overflow-y: auto; + opacity: 0; + position: absolute; + z-index: 999; + will-change: width, height +} + +.dropdown-content li { + clear: both; + color: #000; + cursor: pointer; + line-height: 1.3rem; + width: 100%; + text-align: left; + text-transform: none +} + +.dropdown-content li.active, +.dropdown-content li:hover { + background-color: #eee +} + +.dropdown-content li>a, +.dropdown-content li>span { + font-size: .9rem; + color: #4285F4; + display: block; + padding: .5rem +} + +.dropdown-content li>a>i { + height: inherit; + line-height: inherit +} + +.colorful-select .dropdown-content { + padding: .5rem +} + +.navbar .nav-item.avatar, +.navbar .nav-item.avatar .dropdown-toggle { + padding: 0 +} + +.colorful-select .dropdown-content li.active span { + color: #fff!important +} + +.colorful-select .dropdown-content li.active span [type=checkbox]:checked+label:before { + border-color: transparent #fff #fff transparent +} + +.colorful-select .dropdown-content li a:hover, +.colorful-select .dropdown-content li span:hover { + color: #fff!important; + -webkit-transition: all .1s linear; + transition: all .1s linear; + border-radius: 2px +} + +.colorful-select .dropdown-content li a:hover [type=checkbox]+label:before, +.colorful-select .dropdown-content li span:hover [type=checkbox]+label:before { + border-color: #fff +} + +.colorful-select .dropdown-content li a:hover [type=checkbox]:checked+label:before, +.colorful-select .dropdown-content li span:hover [type=checkbox]:checked+label:before { + border-color: transparent #fff #fff transparent +} + +.colorful-select .dropdown-content li.disabled.active span, +.colorful-select .dropdown-content li.optgroup.active span, +.colorful-select .dropdown-content li:disabled.active span { + color: rgba(0, 0, 0, .3)!important; + border-bottom-color: rgba(0, 0, 0, .3); + cursor: default +} + +.colorful-select .dropdown-content li.disabled a:hover, +.colorful-select .dropdown-content li.disabled span:hover, +.colorful-select .dropdown-content li.optgroup a:hover, +.colorful-select .dropdown-content li.optgroup span:hover, +.colorful-select .dropdown-content li:disabled a:hover, +.colorful-select .dropdown-content li:disabled span:hover { + color: rgba(0, 0, 0, .3)!important; + border-bottom-color: rgba(0, 0, 0, .3); + cursor: default; + background-color: #fff!important +} + +.colorful-select .dropdown-content li.disabled label, +.colorful-select .dropdown-content li.optgroup label, +.colorful-select .dropdown-content li:disabled label { + cursor: default +} + +.dropdown-primary .dropdown-content li a, +.dropdown-primary .dropdown-content li span:hover, +.dropdown-primary .dropdown-content li.active { + background-color: #4285F4 +} + +.dropdown-primary .search-wrap input:focus { + border-bottom: 1px solid #4285F4; + -webkit-box-shadow: 0 1px 0 0 #4285F4; + box-shadow: 0 1px 0 0 #4285F4 +} + +.dropdown-danger .dropdown-content li a, +.dropdown-danger .dropdown-content li span:hover, +.dropdown-danger .dropdown-content li.active { + background-color: #C00 +} + +.dropdown-danger .search-wrap input:focus { + border-bottom: 1px solid #C00; + -webkit-box-shadow: 0 1px 0 0 #C00; + box-shadow: 0 1px 0 0 #C00 +} + +.dropdown-default .dropdown-content li a, +.dropdown-default .dropdown-content li span:hover, +.dropdown-default .dropdown-content li.active { + background-color: #2BBBAD +} + +.dropdown-default .search-wrap input:focus { + border-bottom: 1px solid #2BBBAD; + -webkit-box-shadow: 0 1px 0 0 #2BBBAD; + box-shadow: 0 1px 0 0 #2BBBAD +} + +.dropdown-secondary .dropdown-content li a, +.dropdown-secondary .dropdown-content li span:hover, +.dropdown-secondary .dropdown-content li.active { + background-color: #a6c +} + +.dropdown-secondary .search-wrap input:focus { + border-bottom: 1px solid #a6c; + -webkit-box-shadow: 0 1px 0 0 #a6c; + box-shadow: 0 1px 0 0 #a6c +} + +.dropdown-success .dropdown-content li a, +.dropdown-success .dropdown-content li span:hover, +.dropdown-success .dropdown-content li.active { + background-color: #00C851 +} + +.dropdown-success .search-wrap input:focus { + border-bottom: 1px solid #00C851; + -webkit-box-shadow: 0 1px 0 0 #00C851; + box-shadow: 0 1px 0 0 #00C851 +} + +.dropdown-info .dropdown-content li a, +.dropdown-info .dropdown-content li span:hover, +.dropdown-info .dropdown-content li.active { + background-color: #33b5e5 +} + +.dropdown-info .search-wrap input:focus { + border-bottom: 1px solid #33b5e5; + -webkit-box-shadow: 0 1px 0 0 #33b5e5; + box-shadow: 0 1px 0 0 #33b5e5 +} + +.dropdown-warning .dropdown-content li a, +.dropdown-warning .dropdown-content li span:hover, +.dropdown-warning .dropdown-content li.active { + background-color: #fb3 +} + +.dropdown-warning .search-wrap input:focus { + border-bottom: 1px solid #fb3; + -webkit-box-shadow: 0 1px 0 0 #fb3; + box-shadow: 0 1px 0 0 #fb3 +} + +.dropdown-dark .dropdown-content li a, +.dropdown-dark .dropdown-content li span:hover, +.dropdown-dark .dropdown-content li.active { + background-color: #2E2E2E +} + +.dropdown-dark .search-wrap input:focus { + border-bottom: 1px solid #2E2E2E; + -webkit-box-shadow: 0 1px 0 0 #2E2E2E; + box-shadow: 0 1px 0 0 #2E2E2E +} + +.dropdown-ins .dropdown-content li a, +.dropdown-ins .dropdown-content li span:hover, +.dropdown-ins .dropdown-content li.active { + background-color: #2E5E86 +} + +.dropdown-ins .search-wrap input:focus { + border-bottom: 1px solid #2E5E86; + -webkit-box-shadow: 0 1px 0 0 #2E5E86; + box-shadow: 0 1px 0 0 #2E5E86 +} + +.dropdown-menu.animated { + -webkit-animation-duration: .55s; + animation-duration: .55s; + -webkit-animation-timing-function: ease; + animation-timing-function: ease +} + +.navbar .nav-item.avatar.active { + background-color: transparent!important +} + +.nav-pills .nav-item a.active, +.nav-pills .nav-item a.active:active, +.nav-pills .nav-item a.active:focus, +.nav-pills .nav-item a.active:hover, +.nav-pills .nav-item a:hover { + background-color: transparent; + font-weight: 500 +} + +.navbar .nav-item.avatar .dropdown-toggle img { + height: 35px +} + +.navbar .nav-item.avatar .dropdown-toggle:after { + display: none +} + +.double-nav { + z-index: 100; + color: #fff +} + +@media (max-width: 992px) { + .double-nav { + padding-top: 4px; + padding-bottom: 4px + } +} + +@media (max-width: 768px) { + .double-nav .container { + padding-left: 0; + padding-right: 0 + } +} + +.double-nav a { + color: #fff; + font-size: 15px +} + +.double-nav .breadcrumb-dn p { + margin: 0; + padding-top: 0; + padding-left: 1rem +} + +@media (max-width: 993px) { + .double-nav .breadcrumb-dn { + display: none + } +} + +.double-nav .button-collapse { + position: absolute; + left: 10px; + font-size: 1.5rem +} + +@media (min-width: 1440px) { + .double-nav .button-collapse { + display: none + } +} + +@media (max-width: 1440px) { + .double-nav .button-collapse { + display: block; + position: relative; + font-size: 1.4rem; + margin-right: 10px; + margin-left: 10px + } +} + +.nav-pills .nav-item a { + text-align: left; + color: #666; + border-radius: 0 +} + +.nav-pills .nav-item a:hover { + border-left: 1px solid +} + +.nav-pills .nav-item a.active { + color: #45526E; + border-left: 2px solid; + -webkit-box-shadow: none; + box-shadow: none +} + +.nav-pills .nav-item+.nav-item { + margin-left: 0 +} + +@media only screen and (max-width: 991px) { + .sticky, + .sticky-placeholder { + display: none + } +} + +@media only screen and (max-width: 992px) { + .col-lg-4 .sticky, + .col-md-4 .sticky, + .col-xl-4 .sticky { + width: 200px + } +} + +@media only screen and (min-width: 992px) { + .col-md-4 .sticky .col-lg-4 .sticky, + .col-xl-4 .sticky { + width: 400px + } +} + +@media only screen and (min-width: 1200px) { + .col-md-4 .sticky { + width: 300px + } +} + +@media only screen and (min-width: 1440px) { + .col-md-4 .sticky { + width: 350px + } +} + +.dotted-scrollspy { + display: block; + position: fixed; + top: 50%; + right: 0; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + background: rgba(0, 0, 0, .55); + border-radius: 2px 0 0 2px +} + +.dotted-scrollspy li { + display: block; + padding: 0 16px +} + +.dotted-scrollspy li:first-child { + padding-top: 10px +} + +.dotted-scrollspy li:last-child { + padding-bottom: 10px +} + +.dotted-scrollspy li a { + padding: .5rem +} + +.dotted-scrollspy li a span { + display: block; + background-color: rgba(255, 255, 255, .54); + width: 8px; + height: 8px; + border-radius: 50% +} + +.dotted-scrollspy li a.active span { + background: #fff +} + +.scrollspy-example { + overflow-y: scroll; + position: relative; + height: 200px; + padding: 1rem +} + +.pswp, +.pswp__item, +.pswp__scroll-wrap { + overflow: hidden +} + +.pswp, +.pswp__bg, +.pswp__scroll-wrap { + width: 100%; + height: 100%; + top: 0; + position: absolute; + left: 0 +} + +.pswp { + display: none; + -ms-touch-action: none; + touch-action: none; + z-index: 1500; + -webkit-backface-visibility: hidden; + outline: 0 +} + +.pswp--open, +.pswp__button { + display: block +} + +.pswp * { + -webkit-box-sizing: border-box; + box-sizing: border-box +} + +.pswp img { + max-width: none +} + +.pswp--animate_opacity { + opacity: .001; + will-change: opacity; + -webkit-transition: opacity 333ms cubic-bezier(.4, 0, .22, 1); + transition: opacity 333ms cubic-bezier(.4, 0, .22, 1) +} + +.pswp--zoom-allowed .pswp__img { + cursor: -webkit-zoom-in; + cursor: -moz-zoom-in; + cursor: zoom-in +} + +.pswp--zoomed-in .pswp__img { + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab +} + +.pswp--dragging .pswp__img { + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + cursor: grabbing +} + +.pswp__container, +.pswp__zoom-wrap { + -ms-touch-action: none; + touch-action: none; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + -webkit-backface-visibility: hidden +} + +.pswp__container, +.pswp__img { + user-select: none; + -webkit-touch-callout: none +} + +.pswp__zoom-wrap { + position: absolute; + width: 100%; + -webkit-transform-origin: left top; + -ms-transform-origin: left top; + transform-origin: left top; + -webkit-transition: -webkit-transform 333ms cubic-bezier(.4, 0, .22, 1); + transition: -webkit-transform 333ms cubic-bezier(.4, 0, .22, 1); + transition: transform 333ms cubic-bezier(.4, 0, .22, 1); + transition: transform 333ms cubic-bezier(.4, 0, .22, 1), -webkit-transform 333ms cubic-bezier(.4, 0, .22, 1) +} + +.pswp__bg { + background: #000; + opacity: 0; + -webkit-backface-visibility: hidden; + will-change: opacity; + -webkit-transition: opacity 333ms cubic-bezier(.4, 0, .22, 1); + transition: opacity 333ms cubic-bezier(.4, 0, .22, 1) +} + +.pswp--animated-in .pswp__bg, +.pswp--animated-in .pswp__zoom-wrap { + -webkit-transition: none; + transition: none +} + +.pswp__item { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0 +} + +.pswp__img { + position: absolute; + width: auto; + height: auto; + top: 0; + left: 0 +} + +.pswp__img--placeholder { + -webkit-backface-visibility: hidden +} + +.pswp__img--placeholder--blank { + background: #222 +} + +.pswp--ie .pswp__img { + width: 100%!important; + height: auto!important; + left: 0; + top: 0 +} + +.pswp__error-msg { + position: absolute; + left: 0; + top: 50%; + width: 100%; + text-align: center; + font-size: 14px; + line-height: 16px; + margin-top: -8px; + color: #CCC +} + +.pswp__error-msg a { + color: #CCC; + text-decoration: underline +} + +.pswp__share-tooltip a, +.pswp__share-tooltip a:hover { + text-decoration: none; + color: #000 +} + +.pswp__button { + position: relative; + cursor: pointer; + overflow: visible; + border: 0; + padding: 0; + margin: 0; + float: right; + opacity: .75; + -webkit-transition: opacity .2s; + transition: opacity .2s; + -webkit-box-shadow: none; + box-shadow: none +} + +.mdb-autocomplete-wrap, +.pswp__share-tooltip { + -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, .25) +} + +.pswp__button:focus, +.pswp__button:hover { + opacity: 1 +} + +.pswp__button:active { + outline: 0; + opacity: .9 +} + +.pswp__button::-moz-focus-inner { + padding: 0; + border: 0 +} + +.pswp__ui--over-close .pswp__button--close { + opacity: 1 +} + +.pswp__button, +.pswp__button--arrow--left:before, +.pswp__button--arrow--right:before { + background: url(../img/lightbox/default-skin.png) no-repeat; + background-size: 264px 88px; + width: 44px; + height: 44px +} + +@media (-webkit-min-device-pixel-ratio: 1.1), +(-webkit-min-device-pixel-ratio:1.09375), +(min-resolution:105dpi), +(min-resolution:1.1dppx) { + .pswp--svg .pswp__button, + .pswp--svg .pswp__button--arrow--left:before, + .pswp--svg .pswp__button--arrow--right:before { + background-image: url(../img/lightbox/default-skin.svg) + } + .pswp--svg .pswp__button--arrow--left, + .pswp--svg .pswp__button--arrow--right { + background: 0 0 + } +} + +.pswp__button--close { + background-position: 0 -44px +} + +.pswp__button--share { + background-position: -44px -44px +} + +.pswp__button--fs { + display: none +} + +.pswp--supports-fs .pswp__button--fs { + display: block +} + +.pswp--fs .pswp__button--fs { + background-position: -44px 0 +} + +.pswp__button--zoom { + display: none; + background-position: -88px 0 +} + +.pswp--zoom-allowed .pswp__button--zoom { + display: block +} + +.pswp--zoomed-in .pswp__button--zoom { + background-position: -132px 0 +} + +.pswp__button--arrow--left, +.pswp__button--arrow--right { + background: 0 0; + top: 50%; + margin-top: -50px; + width: 70px; + height: 100px; + position: absolute +} + +.pswp__button--arrow--left { + left: 0 +} + +.pswp__button--arrow--right { + right: 0 +} + +.pswp__button--arrow--left:before, +.pswp__button--arrow--right:before { + content: ''; + top: 35px; + background-color: rgba(0, 0, 0, .3); + height: 30px; + width: 32px; + position: absolute +} + +.pswp__button--arrow--left:before { + left: 6px; + background-position: -138px -44px +} + +.pswp__button--arrow--right:before { + right: 6px; + background-position: -94px -44px +} + +.pswp__counter, +.pswp__share-modal { + user-select: none +} + +.pswp__share-modal { + display: block; + background: rgba(0, 0, 0, .5); + width: 100%; + height: 100%; + top: 0; + left: 0; + padding: 10px; + position: absolute; + z-index: 1600; + opacity: 0; + -webkit-transition: opacity .25s ease-out; + transition: opacity .25s ease-out; + -webkit-backface-visibility: hidden; + will-change: opacity +} + +.pswp__share-modal--hidden { + display: none +} + +.pswp__share-tooltip { + z-index: 1620; + position: absolute; + background: #FFF; + top: 56px; + border-radius: 2px; + display: block; + width: auto; + right: 44px; + box-shadow: 0 2px 5px rgba(0, 0, 0, .25); + -webkit-transform: translateY(6px); + -ms-transform: translateY(6px); + transform: translateY(6px); + -webkit-transition: -webkit-transform .25s; + transition: -webkit-transform .25s; + transition: transform .25s; + transition: transform .25s, -webkit-transform .25s; + -webkit-backface-visibility: hidden; + will-change: transform +} + +.chips, +.progress { + -webkit-box-shadow: none +} + +.pswp__share-tooltip a { + display: block; + padding: 8px 12px; + font-size: 14px; + line-height: 18px +} + +.pswp__share-tooltip a:first-child { + border-radius: 2px 2px 0 0 +} + +.pswp__share-tooltip a:last-child { + border-radius: 0 0 2px 2px +} + +.pswp__share-modal--fade-in { + opacity: 1 +} + +.pswp__share-modal--fade-in .pswp__share-tooltip { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0) +} + +.pswp--touch .pswp__share-tooltip a { + padding: 16px 12px +} + +a.pswp__share--facebook:before { + content: ''; + display: block; + width: 0; + height: 0; + position: absolute; + top: -12px; + right: 15px; + border: 6px solid transparent; + border-bottom-color: #FFF; + -webkit-pointer-events: none; + -moz-pointer-events: none; + pointer-events: none +} + +.pswp__caption--empty, +.pswp__ui--one-slide .pswp__button--arrow--left, +.pswp__ui--one-slide .pswp__button--arrow--right, +.pswp__ui--one-slide .pswp__counter { + display: none +} + +.pswp__counter, +.pswp__preloader { + height: 44px; + top: 0; + position: absolute +} + +a.pswp__share--facebook:hover { + background: #3E5C9A; + color: #FFF +} + +a.pswp__share--facebook:hover:before { + border-bottom-color: #3E5C9A +} + +a.pswp__share--twitter:hover { + background: #55ACEE; + color: #FFF +} + +a.pswp__share--pinterest:hover { + background: #CCC; + color: #CE272D +} + +a.pswp__share--download:hover { + background: #DDD +} + +.pswp__counter { + left: 0; + font-size: 13px; + line-height: 44px; + color: #FFF; + opacity: .75; + padding: 0 10px +} + +.pswp__caption { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + min-height: 44px +} + +.pswp__caption small { + font-size: 11px; + color: #BBB +} + +.pswp__caption__center { + text-align: left; + max-width: 420px; + margin: 0 auto; + font-size: 13px; + padding: 10px; + line-height: 20px; + color: #CCC +} + +.carousel-multi-item .controls-top, +.cart-modal .table, +.cart-modal th, +.comments-list h4, +.product-panel .modal-header, +.ql-modal .modal-header, +.reply-form h4, +.side-nav .about p, +.side-nav .social, +.stepper li a, +.stepper li a .circle, +input[type=range]+.thumb .value { + text-align: center +} + +.chip, +.chip .close, +.chips .input { + line-height: 32px +} + +.pswp--has_mouse .pswp__button--arrow--left, +.pswp--has_mouse .pswp__button--arrow--right, +.pswp__ui { + visibility: visible +} + +.pswp__preloader { + width: 44px; + left: 50%; + margin-left: -22px; + opacity: 0; + -webkit-transition: opacity .25s ease-out; + transition: opacity .25s ease-out; + will-change: opacity; + direction: ltr +} + +.pswp--css_animation .pswp__preloader--active, +.pswp__preloader--active { + opacity: 1 +} + +.pswp__preloader__icn { + width: 20px; + height: 20px; + margin: 12px +} + +.pswp__preloader--active .pswp__preloader__icn { + background: url(../img/lightbox/preloader.gif) no-repeat +} + +.pswp--css_animation .pswp__preloader--active .pswp__preloader__icn { + -webkit-animation: clockwise .5s linear infinite; + animation: clockwise .5s linear infinite +} + +.pswp--css_animation .pswp__preloader--active .pswp__preloader__donut { + -webkit-animation: donut-rotate 1s cubic-bezier(.4, 0, .22, 1) infinite; + animation: donut-rotate 1s cubic-bezier(.4, 0, .22, 1) infinite +} + +.pswp--css_animation .pswp__preloader__icn { + background: 0 0; + opacity: .75; + width: 14px; + height: 14px; + position: absolute; + left: 15px; + top: 15px; + margin: 0 +} + +.pswp--css_animation .pswp__preloader__cut { + position: relative; + width: 7px; + height: 14px; + overflow: hidden +} + +.pswp--css_animation .pswp__preloader__donut { + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 14px; + height: 14px; + border: 2px solid #FFF; + border-radius: 50%; + border-left-color: transparent; + border-bottom-color: transparent; + position: absolute; + top: 0; + left: 0; + background: 0 0; + margin: 0 +} + +@media screen and (max-width: 1024px) { + .pswp__preloader { + position: relative; + left: auto; + top: auto; + margin: 0; + float: right + } +} + +@-webkit-keyframes clockwise { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0) + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +@keyframes clockwise { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0) + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +@-webkit-keyframes donut-rotate { + 0%, + 100% { + -webkit-transform: rotate(0); + transform: rotate(0) + } + 50% { + -webkit-transform: rotate(-140deg); + transform: rotate(-140deg) + } +} + +@keyframes donut-rotate { + 0%, + 100% { + -webkit-transform: rotate(0); + transform: rotate(0) + } + 50% { + -webkit-transform: rotate(-140deg); + transform: rotate(-140deg) + } +} + +.pswp__ui { + -webkit-font-smoothing: auto; + opacity: 1; + z-index: 1550 +} + +.pswp__top-bar { + position: absolute; + left: 0; + top: 0; + height: 44px; + width: 100% +} + +.pswp--has_mouse .pswp__button--arrow--left, +.pswp--has_mouse .pswp__button--arrow--right, +.pswp__caption, +.pswp__top-bar { + -webkit-backface-visibility: hidden; + will-change: opacity; + -webkit-transition: opacity 333ms cubic-bezier(.4, 0, .22, 1); + transition: opacity 333ms cubic-bezier(.4, 0, .22, 1) +} + +.pswp__caption, +.pswp__top-bar { + background-color: rgba(0, 0, 0, .5) +} + +.pswp__ui--fit .pswp__caption, +.pswp__ui--fit .pswp__top-bar { + background-color: rgba(0, 0, 0, .3) +} + +.pswp__ui--idle .pswp__button--arrow--left, +.pswp__ui--idle .pswp__button--arrow--right, +.pswp__ui--idle .pswp__top-bar { + opacity: 0 +} + +.pswp__ui--hidden .pswp__button--arrow--left, +.pswp__ui--hidden .pswp__button--arrow--right, +.pswp__ui--hidden .pswp__caption, +.pswp__ui--hidden .pswp__top-bar { + opacity: .001 +} + +.pswp__element--disabled { + display: none!important +} + +.pswp--minimal--dark .pswp__top-bar { + background: 0 0 +} + +.mdb-lightbox figure { + margin: 0; + float: left +} + +.comments-list .mdb-lightbox figure img, +.mdb-lightbox figure .comments-list img, +.mdb-lightbox figure .img-fluid, +.mdb-lightbox figure .modal-dialog.cascading-modal.modal-avatar .modal-header, +.mdb-lightbox figure .reply-form img, +.mdb-lightbox figure .section-blog-fw .view img, +.modal-dialog.cascading-modal.modal-avatar .mdb-lightbox figure .modal-header, +.reply-form .mdb-lightbox figure img, +.section-blog-fw .view .mdb-lightbox figure img { + display: inline +} + +.chip, +.chips .input { + display: inline-block +} + +.mdb-lightbox figure img { + cursor: -webkit-zoom-in; + cursor: zoom-in; + -webkit-transition: opacity .4s; + transition: opacity .4s; + border-radius: 0 +} + +.mdb-lightbox figure img:hover { + opacity: .8 +} + +.mdb-lightbox.no-margin [class*=col-] { + padding: 0 +} + +.mdb-lightbox [class*=col-] { + padding: .5rem +} + +.chip { + height: 32px; + font-size: 13px; + font-weight: 500; + color: rgba(0, 0, 0, .6); + padding: 0 12px; + border-radius: 16px; + background-color: #eceff1; + margin-bottom: 1rem; + margin-right: 1rem +} + +.chip img { + float: left; + margin: 0 8px 0 -12px; + height: 32px; + width: 32px; + border-radius: 50% +} + +.chip .close { + cursor: pointer; + float: right; + font-size: 16px; + padding-left: 8px; + -webkit-transition: all .1s linear; + transition: all .1s linear +} + +.chips { + outline: 0; + box-shadow: none; + border: none; + border-bottom: 1px solid #bdbdbd; + margin-bottom: 30px; + min-height: 45px; + padding-bottom: 1rem; + -webkit-transition: all .3s; + transition: all .3s +} + +.chips.focus { + border-bottom: 1px solid #4285F4; + -webkit-box-shadow: 0 1px 0 0 #4285F4; + box-shadow: 0 1px 0 0 #4285F4 +} + +.chips:hover { + cursor: text +} + +.chips .tag.selected { + border-bottom: 1px solid #4285F4; + color: #fff +} + +.chips .input { + background: 0 0; + border: 0; + outline: 0; + padding: 0!important; + width: 120px!important; + color: rgba(0, 0, 0, .6); + font-size: 13px; + font-weight: 500; + height: 32px; + margin-right: 20px +} + +.chips .input:focus { + border: 0!important; + -webkit-box-shadow: none!important; + box-shadow: none!important +} + +.table a { + margin-left: 1rem +} + +.table fieldset { + margin-bottom: 0 +} + +.table fieldset label { + height: 8px +} + +.product-table img { + max-height: 150px; + min-width: 50px +} + +[type=radio], +[type=checkbox] { + position: absolute; + left: -9999px; + visibility: hidden +} + +[type=radio]+label, +[type=checkbox]+label { + position: relative; + padding-left: 35px; + cursor: pointer; + display: inline-block; + height: 25px; + line-height: 25px; + font-size: 1rem; + -webkit-user-select: none; + -moz-user-select: none; + -khtml-user-select: none; + -ms-user-select: none +} + +.streak { + display: block; + position: relative; + overflow: hidden; + height: 250px +} + +.streak.streak-md { + height: 400px +} + +@media (max-width: 736px) { + .streak.streak-md { + height: 300px + } +} + +.streak.streak-lg { + height: 650px +} + +@media (max-width: 450px) { + .streak.streak-lg { + height: 900px + } +} + +.streak.streak-long { + height: 200px +} + +@media (max-width: 450px) { + .streak.streak-long { + height: 620px + } +} + +.streak.streak-long-2 { + height: 400px +} + +@media (max-width: 450px) { + .streak.streak-long-2 { + height: 700px + } +} + +.streak.streak-photo { + background-repeat: no-repeat; + background-size: cover; + background-position: center +} + +@media (min-width: 1366px) { + .streak.streak-photo { + background-attachment: fixed + } +} + +.streak.no-flex { + padding-top: 3.125rem; + padding-bottom: 3.125rem; + height: auto +} + +.purple-gradient { + background: -webkit-linear-gradient(50deg, #ff6ec4, #7873f5); + background: linear-gradient(40deg, #ff6ec4, #7873f5) +} + +.peach-gradient { + background: -webkit-linear-gradient(50deg, #FFD86F, #FC6262); + background: linear-gradient(40deg, #FFD86F, #FC6262) +} + +.aqua-gradient { + background: -webkit-linear-gradient(50deg, #2096ff, #05ffa3); + background: linear-gradient(40deg, #2096ff, #05ffa3) +} + +.blue-gradient { + background: -webkit-linear-gradient(50deg, #45cafc, #303f9f); + background: linear-gradient(40deg, #45cafc, #303f9f) +} + +[type=radio]+label { + -webkit-transition: .28s ease; + transition: .28s ease +} + +[type=radio]+label:after, +[type=radio]+label:before { + content: ''; + position: absolute; + left: 0; + top: 0; + margin: 4px; + width: 16px; + height: 16px; + z-index: 0; + border-radius: 50%; + border-style: solid; + border-width: 2px; + -webkit-transition: .28s ease; + transition: .28s ease +} + +[type=radio]:not(:checked)+label:after, +[type=radio]:not(:checked)+label:before { + border-color: #5a5a5a +} + +[type=radio]:not(:checked)+label:after { + z-index: -1; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0) +} + +[type=radio]:checked+label:before { + border-color: transparent +} + +[type=radio]:checked+label:after { + border-color: #4285F4; + background-color: #4285F4; + z-index: 0; + -webkit-transform: scale(1.02); + -ms-transform: scale(1.02); + transform: scale(1.02) +} + +[type=radio]:disabled+label { + color: rgba(0, 0, 0, .46) +} + +[type=radio]:disabled+label:before { + background-color: transparent; + border-color: rgba(0, 0, 0, .46) +} + +[type=radio]:disabled:not(:checked)+label:before { + border-color: rgba(0, 0, 0, .46) +} + +[type=radio]:disabled:checked+label:after { + background-color: rgba(0, 0, 0, .46); + border-color: #BDBDBD +} + +[type=radio].with-gap:checked+label:before { + border-color: #4285F4 +} + +[type=radio].with-gap:checked+label:after { + -webkit-transform: scale(.5); + -ms-transform: scale(.5); + transform: scale(.5) +} + +[type=radio].with-gap:checked:disabled+label:before { + border-color: rgba(0, 0, 0, .46) +} + +[type=checkbox]+label:before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 17px; + height: 17px; + z-index: 0; + border: 1.5px solid #8a8a8a; + border-radius: 1px; + margin-top: 2px; + -webkit-transition: .2s; + transition: .2s +} + +[type=checkbox]:checked+label:before { + top: -4px; + left: -3px; + width: 12px; + height: 22px; + border-style: solid; + border-width: 2px; + border-color: transparent #4285F4 #4285F4 transparent; + -webkit-transform: rotate(40deg); + -ms-transform: rotate(40deg); + transform: rotate(40deg); + -webkit-backface-visibility: hidden; + -webkit-transform-origin: 100% 100%; + -ms-transform-origin: 100% 100%; + transform-origin: 100% 100% +} + +[type=checkbox]:indeterminate+label:before { + left: -10px; + top: -11px; + width: 10px; + height: 22px; + border: none; + border-right: 2px solid #4285F4; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + -webkit-backface-visibility: hidden; + -webkit-transform-origin: 100% 100%; + -ms-transform-origin: 100% 100%; + transform-origin: 100% 100% +} + +[type=checkbox]:disabled:checked+label:before { + border-color: transparent rgba(0, 0, 0, .46) rgba(0, 0, 0, .46) transparent +} + +[type=checkbox]:disabled:not(:checked)+label:before { + border: none; + margin-left: 2px; + margin-top: 2px; + background-color: rgba(0, 0, 0, .46) +} + +[type=checkbox]:disabled:indeterminate+label:before { + border-right: 2px solid rgba(0, 0, 0, .46); + margin-left: 0; + margin-top: 0; + background-color: transparent +} + +[type=checkbox][class*=filled-in]+label:after, +[type=checkbox][class*=filled-in]+label:before { + content: ''; + left: 0; + position: absolute; + -webkit-transition: border .25s, background-color .25s, width .2s .1s, height .2s .1s, top .2s .1s, left .2s .1s; + transition: border .25s, background-color .25s, width .2s .1s, height .2s .1s, top .2s .1s, left .2s .1s; + z-index: 1; + border-style: solid; + border-width: 2px +} + +[type=checkbox][class*=filled-in]+label:after { + border-radius: 2px; + height: 20px; + width: 20px +} + +[type=checkbox][class*=filled-in]+label:before { + -webkit-transform: rotateZ(37deg); + -ms-transform: rotateZ(37deg); + transform: rotateZ(37deg); + -webkit-transform-origin: 100% 100%; + -ms-transform-origin: 100% 100%; + transform-origin: 100% 100% +} + +[type=checkbox][class*=filled-in]:not(:checked)+label:before { + width: 0; + height: 0; + border-style: 3px; + border-color: transparent; + left: 6px; + top: 10px +} + +[type=checkbox][class*=filled-in]:not(:checked)+label:after { + background-color: transparent; + border-color: #5a5a5a; + top: 0; + z-index: 0 +} + +[type=checkbox][class*=filled-in]:checked+label:before { + top: 0; + left: 1px; + width: 8px; + height: 13px; + border-color: transparent #fff #fff transparent +} + +[type=checkbox][class*=filled-in]:checked+label:after { + border-color: #a6c; + background-color: #a6c; + z-index: 0 +} + +[type=checkbox][class*=filled-in]:disabled:not(:checked)+label:before { + background-color: transparent; + border-color: #BDBDBD +} + +[type=checkbox][class*=filled-in]:disabled:not(:checked)+label:after { + border-color: transparent; + background-color: #BDBDBD +} + +[type=checkbox][class*=filled-in]:disabled:checked+label:before { + background-color: transparent +} + +[type=checkbox][class*=filled-in]:disabled:checked+label:after { + background-color: #BDBDBD; + border-color: #BDBDBD +} + +[type=checkbox].filled-in-danger:checked+label:after { + background-color: red; + border-color: red +} + +.select-wrapper .select-dropdown { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none +} + +.clockpicker-plate, +.picker, +.switch, +.switch * { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none +} + +.select-label { + position: absolute +} + +.select-wrapper { + position: relative +} + +.select-wrapper input.select-dropdown { + position: relative; + cursor: pointer; + background-color: transparent; + border: none; + border-bottom-style: solid; + border-bottom-width: 1px; + border-bottom-color: #bdbdbd; + outline: 0; + height: 3rem; + line-height: 3rem; + width: 100%; + font-size: 1rem; + margin: 0 0 15px; + padding: 0; + display: block +} + +.select-wrapper input.select-dropdown:disabled { + color: rgba(0, 0, 0, .3); + border-bottom-color: rgba(0, 0, 0, .3); + cursor: default +} + +.select-wrapper .search-wrap { + padding: 1rem 0; + width: 93%; + display: block; + margin: 0 auto +} + +.select-wrapper .search-wrap input { + padding-bottom: .4rem +} + +.select-wrapper span.caret { + color: initial; + position: absolute; + right: 0; + top: 16px; + font-size: 10px +} + +.select-wrapper span.caret.disabled { + color: rgba(0, 0, 0, .46) +} + +.select-wrapper i, +select:disabled { + color: rgba(0, 0, 0, .3) +} + +.select-wrapper+label { + position: absolute; + top: -14px; + font-size: .8rem +} + +.select-wrapper ul { + list-style-type: none; + padding-left: 0 +} + +select { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + display: none!important +} + +select.browser-default { + display: block!important +} + +.switch label .lever, +.switch label .lever:after { + display: inline-block; + content: "" +} + +.select-dropdown ul { + list-style-type: none; + padding: 0 +} + +.select-dropdown li img { + height: 30px; + width: 30px; + margin: 3px 12px; + float: right +} + +.select-dropdown li.disabled, +.select-dropdown li.disabled>span, +.select-dropdown li.optgroup { + color: rgba(0, 0, 0, .3); + background-color: transparent!important; + cursor: context-menu +} + +.select-dropdown li.optgroup { + border-top: 1px solid #eee +} + +.select-dropdown li.optgroup.selected>span { + color: rgba(0, 0, 0, .7) +} + +.select-dropdown li.optgroup>span { + color: rgba(0, 0, 0, .4) +} + +.multiple-select-dropdown li [type=checkbox]+label { + height: 10px +} + +.switch, +.switch * { + -khtml-user-select: none +} + +.switch label { + cursor: pointer +} + +.switch label input[type=checkbox] { + opacity: 0; + width: 0; + height: 0 +} + +.switch label input[type=checkbox]:checked+.lever { + background-color: #dccfe2 +} + +.switch label input[type=checkbox]:checked+.lever:after { + background-color: #a6c; + left: 24px +} + +.switch label input[type=checkbox]:checked:not(:disabled)~.lever:active:after { + -webkit-box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .4), 0 0 0 15px rgba(170, 102, 204, .1); + box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .4), 0 0 0 15px rgba(170, 102, 204, .1) +} + +.switch label input[type=checkbox]:not(:disabled)~.lever:active:after { + -webkit-box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .4), 0 0 0 15px rgba(0, 0, 0, .08); + box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .4), 0 0 0 15px rgba(0, 0, 0, .08) +} + +.switch label input[type=checkbox]:disabled+.lever { + cursor: default +} + +.switch label input[type=checkbox]:disabled+.lever:after, +.switch label input[type=checkbox]:disabled:checked+.lever:after { + background-color: #BDBDBD +} + +.switch label .lever { + position: relative; + width: 40px; + height: 15px; + background-color: #818181; + border-radius: 15px; + -webkit-transition: background .3s ease; + transition: background .3s ease; + margin: 0 16px +} + +.switch label .lever:after { + position: absolute; + width: 21px; + height: 21px; + background-color: #F1F1F1; + border-radius: 21px; + -webkit-box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .4); + box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .4); + left: -5px; + top: -3px; + -webkit-transition: left .3s ease, background .3s ease, box-shadow .1s ease; + -webkit-transition: left .3s ease, background .3s ease, -webkit-box-shadow .1s ease; + transition: left .3s ease, background .3s ease, -webkit-box-shadow .1s ease; + transition: left .3s ease, background .3s ease, box-shadow .1s ease; + transition: left .3s ease, background .3s ease, box-shadow .1s ease, -webkit-box-shadow .1s ease +} + +.file-field { + position: relative +} + +.file-field .file-path-wrapper { + overflow: hidden; + padding-left: 10px; + height: 2.5rem +} + +.file-field input.file-path { + width: 100%; + height: 2.1rem +} + +.file-field .btn { + float: left +} + +.file-field span { + cursor: pointer +} + +.file-field input[type=file] { + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + width: 100%; + margin: 0; + padding: 0; + font-size: 1px; + cursor: pointer; + opacity: 0; + filter: alpha(opacity=0) +} + +.range-field, +input[type=range] { + position: relative +} + +.btn-file { + padding-top: 1px +} + +input[type=range] { + cursor: pointer; + background-color: transparent; + outline: 0; + width: 100%; + margin: 15px 0; + padding: 0; + border: 1px solid #fff +} + +input[type=range]:focus { + outline: 0 +} + +input[type=range]+.thumb { + position: absolute; + border: none; + height: 0; + width: 0; + border-radius: 50%; + background-color: #4285F4; + top: 10px; + margin-left: -6px; + -webkit-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + transform-origin: 50% 50%; + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg) +} + +input[type=range]+.thumb .value { + display: block; + width: 30px; + color: #4285F4; + font-size: 0; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg) +} + +input[type=range]+.thumb.active { + border-radius: 50% 50% 50% 0 +} + +input[type=range]+.thumb.active .value { + color: #fff; + margin-left: -1px; + margin-top: 8px; + font-size: 10px +} + +input[type=range]::-webkit-slider-runnable-track { + height: 3px; + background: #c2c0c2; + border: none +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 14px; + width: 14px; + border-radius: 50%; + background-color: #4285F4; + -webkit-transform-origin: 50% 50%; + transform-origin: 50% 50%; + margin: -5px 0 0; + -webkit-transition: .3s; + transition: .3s +} + +input[type=range]:focus::-webkit-slider-runnable-track { + background: #ccc +} + +input[type=range]::-moz-range-track { + height: 3px; + background: #ddd; + border: none +} + +input[type=range]::-moz-range-thumb { + border: none; + height: 14px; + width: 14px; + border-radius: 50%; + background: #4285F4; + margin-top: -5px +} + +input[type=range]:-moz-focusring { + outline: #fff solid 1px; + outline-offset: -1px +} + +input[type=range]:focus::-moz-range-track { + background: #ccc +} + +input[type=range]::-ms-track { + height: 3px; + background: 0 0; + border-color: transparent; + border-width: 6px 0; + color: transparent +} + +input[type=range]::-ms-fill-lower { + background: #777 +} + +input[type=range]::-ms-fill-upper { + background: #ddd +} + +input[type=range]::-ms-thumb { + border: none; + height: 14px; + width: 14px; + border-radius: 50%; + background: #4285F4 +} + +input[type=range]:focus::-ms-fill-lower { + background: #888 +} + +input[type=range]:focus::-ms-fill-upper { + background: #ccc +} + +.input-group .input-group-addon { + background-color: #e0e0e0 +} + +.input-group .input-group-addon [type=checkbox]+label { + padding-left: 18px; + height: 13px +} + +.input-group .input-group-addon [type=radio]+label { + padding-left: 24px; + height: 13px +} + +.input-group .input-group-addon:-moz-placeholder { + padding-left: 1rem +} + +.input-group .input-group-addon::-ms-placeholder { + padding-left: 1rem +} + +.input-group .input-group-addon::-webkit-input-placeholder { + padding-left: 1rem +} + +.input-group .input-group-addon::-moz-placeholder { + padding-left: 1rem +} + +.input-group .input-group-addon:-ms-input-placeholder { + padding-left: 1rem +} + +.input-group .input-group-addon::placeholder { + padding-left: 1rem +} + +.input-group span { + z-index: 10 +} + +.input-group .form-control { + margin-top: 3px; + padding-top: 14px; + padding-bottom: 7px; + padding-left: 1.2rem +} + +.mdb-autocomplete { + margin-bottom: 1px +} + +.mdb-autocomplete-clear { + visibility: hidden; + position: absolute; + z-index: 2; + right: 0; + top: .85rem; + background: 0 0; + border: none +} + +.side-nav .collapsible a.active, +.side-nav .collapsible a:hover, +.side-nav .collapsible>li { + border-radius: 2px +} + +.side-nav .about, +.side-nav .social { + border-bottom: 1px solid rgba(153, 153, 153, .3) +} + +.mdb-autocomplete-clear svg { + fill: #a6a6a6 +} + +.mdb-autocomplete-wrap { + position: absolute; + left: 0; + right: 0; + background: #fff; + box-shadow: 0 2px 5px rgba(0, 0, 0, .25); + z-index: 100; + max-height: 210px; + overflow-y: auto; + padding-left: 0; + list-style-type: none +} + +.mdb-autocomplete-wrap li { + cursor: pointer; + padding: 12px 15px; + font-size: .875rem +} + +.mdb-autocomplete-wrap li:hover { + background: #eee +} + +.jarallax, +.side-nav { + background-size: cover; + background-repeat: no-repeat; + background-position: center +} + +.jarallax { + min-height: 700px +} + +.side-nav { + position: fixed; + width: 240px; + left: 0; + top: 0; + margin: 0; + height: 100%; + height: -webkit-calc(100%+ 60px); + height: calc(100%+ 60px); + height: -moz-calc(100%); + color: #d8d8d8; + background-color: #2c2f34; + z-index: 999; + -webkit-backface-visibility: hidden; + overflow: hidden; + will-change: transform; + backface-visibility: hidden; + -webkit-transform: translateX(-105%); + -ms-transform: translateX(-105%); + transform: translateX(-105%); + list-style-type: none; + padding: 0 +} + +.side-nav ul { + list-style-type: none +} + +.side-nav ul li { + padding: 0 +} + +.side-nav.right-aligned { + right: 0; + left: auto; + -webkit-transform: translateX(100%); + -ms-transform: translateX(100%); + transform: translateX(100%) +} + +.side-nav .collapsible { + margin: 0; + padding: 0 +} + +.side-nav .collapsible li a:hover { + background-color: rgba(0, 0, 0, .15) +} + +.side-nav .collapsible>li a.collapsible-header.active, +.side-nav .collapsible>li a.collapsible-header:hover { + background-color: rgba(255, 255, 255, .15) +} + +.side-nav .collapsible ul { + padding: 0; + list-style-type: none +} + +.side-nav .collapsible a { + color: #fff; + font-weight: 300; + font-size: .8rem +} + +.side-nav .collapsible .fa { + font-size: .8rem; + margin-right: 13px +} + +.side-nav .collapsible-body a { + padding-left: 47px; + height: 36px; + line-height: 36px; + background-color: rgba(0, 0, 0, .15) +} + +.side-nav a { + display: block; + font-size: 1rem; + height: 56px; + line-height: 56px; + padding-left: 20px +} + +.side-nav .logo-wrapper { + height: 140px +} + +.side-nav .logo-wrapper a { + height: 140px; + width: 240px; + padding: 0 +} + +.side-nav .logo-wrapper img { + height: auto; + padding: 20% 50px +} + +@media (max-height: 992px) { + .side-nav .logo-wrapper, + .side-nav .logo-wrapper a { + height: 80px + } + .side-nav .logo-wrapper img { + padding: 7% 50px + } +} + +.side-nav .about { + padding: 1rem +} + +.side-nav .about p { + margin-bottom: 0 +} + +.side-nav .social { + padding: 0 +} + +.side-nav .social li { + display: inline-block; + padding: 0; + margin: 0 +} + +.side-nav .social a { + padding: 0 .6rem; + margin: 0 +} + +.side-nav .social .fa { + color: #dbe4e7 +} + +.side-nav .search-form { + padding: 0 +} + +.side-nav .search-form input[type=text] { + font-weight: 300; + padding-left: 30px +} + +.side-nav .search-form input[type=text]:-moz-placeholder { + color: #fff!important +} + +.side-nav .search-form input[type=text]::-ms-placeholder { + color: #fff!important +} + +.side-nav .search-form input[type=text]::-webkit-input-placeholder { + color: #fff!important +} + +.side-nav .search-form input[type=text]::-moz-placeholder { + color: #fff!important +} + +.side-nav .search-form input[type=text]:-ms-input-placeholder { + color: #fff!important +} + +.side-nav .search-form input[type=text]::placeholder { + color: #fff!important +} + +.side-nav .search-form .form-control { + margin-bottom: 0 +} + +.side-nav .sn-avatar-wrapper { + padding-left: 33%; + padding-right: 33%; + padding-top: 10% +} + +.side-nav .sn-avatar-wrapper img { + margin: 0; + padding: 0; + max-width: 90px; + border-radius: 5rem +} + +@media only screen and (max-height: 992px) { + .side-nav .sn-avatar-wrapper { + padding-left: 40%; + padding-right: 40%; + padding-top: 3% + } + .side-nav .sn-avatar-wrapper img { + max-width: 50px + } +} + +.side-nav .sn-ad-avatar-wrapper { + height: auto; + margin-bottom: 0 +} + +.side-nav .sn-ad-avatar-wrapper img { + max-width: 60px; + padding: 20px 10px; + float: left +} + +.side-nav .sn-ad-avatar-wrapper p { + font-size: 15px; + padding-top: 20px; + padding-bottom: 20px; + margin: 0 +} + +.side-nav .user-box { + padding: 20px 10px 0 +} + +.side-nav .user-box img { + margin: 0 auto 10px; + max-width: 80px +} + +.side-nav .fa-angle-down.rotate-icon { + position: absolute; + right: 0; + margin-right: 20px +} + +.side-nav .sidenav-bg { + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 240px; + z-index: -1; + background-attachment: fixed +} + +.side-nav .sidenav-bg:after { + width: 100%; + display: block; + content: ""; + position: absolute; + height: 100%; + top: 0; + left: 0; + bottom: 0; + z-index: -1; + margin-bottom: -99999px; + padding-bottom: 99999px +} + +.side-nav.fixed { + left: 0; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + position: fixed +} + +.side-nav.fixed.right-aligned { + right: 0; + left: auto +} + +@media only screen and (max-width: 1440px) { + .side-nav.fixed { + -webkit-transform: translateX(-105%); + -ms-transform: translateX(-105%); + transform: translateX(-105%) + } + .side-nav.fixed.right-aligned { + -webkit-transform: translateX(105%); + -ms-transform: translateX(105%); + transform: translateX(105%) + } +} + +.side-nav.side-nav-light { + background-color: #e5e5e5 +} + +.side-nav.side-nav-light a { + color: #555; + font-weight: 400 +} + +.side-nav.side-nav-light .social .fa { + color: #555 +} + +.side-nav.side-nav-light .search-form input[type=text] { + border-bottom-color: rgba(153, 153, 153, .3); + color: #555!important +} + +.side-nav.side-nav-light .search-form input[type=text]:-moz-placeholder { + color: #555!important +} + +.side-nav.side-nav-light .search-form input[type=text]::-ms-placeholder { + color: #555!important +} + +.side-nav.side-nav-light .search-form input[type=text]::-webkit-input-placeholder { + color: #555!important +} + +.side-nav.side-nav-light .search-form input[type=text]::-moz-placeholder { + color: #555!important +} + +.side-nav.side-nav-light .search-form input[type=text]:-ms-input-placeholder { + color: #555!important +} + +.side-nav.side-nav-light .search-form input[type=text]::placeholder { + color: #555!important +} + +.side-nav.side-nav-light .collapsible-body a { + background-color: rgba(0, 0, 0, .1) +} + +.side-nav.side-nav-light .collapsible li .collapsible-header:hover { + background-color: rgba(0, 0, 0, .05) +} + +.side-nav.side-nav-light .collapsible li .collapsible-header.active { + color: #4285F4; + background-color: transparent +} + +.drag-target { + height: 100%; + width: 10px; + position: fixed; + top: 0; + z-index: 998 +} + +#sidenav-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + height: 120vh; + background-color: rgba(0, 0, 0, .5); + z-index: 997; + will-change: opacity +} + +.side-nav .double-navbar .bc-min { + padding: 5px 10px +} + +.no-padding .fa, +.rating { + padding: 0 +} + +.side-nav .double-navbar .bc-min .button-collapse { + padding-left: 0 +} + +.rating { + list-style-type: none +} + +.rating li { + display: inline-block +} + +.product-panel .modal-dialog, +.ql-modal .modal-dialog { + max-width: none; + width: auto; + margin: 2rem +} + +.product-panel .price .badge, +.ql-modal .price .badge { + background-color: rgba(244, 67, 54, .7); + font-size: 1.4rem; + display: inline-block; + margin-left: 1rem +} + +.product-panel .price p, +.ql-modal .price p { + display: inline-block; + font-size: 1.3rem +} + +.product-panel .price p .price-before, +.ql-modal .price p .price-before { + color: #000; + text-decoration: line-through; + margin-left: .5rem +} + +.product-panel .price p .price-after, +.ql-modal .price p .price-after { + font-size: 1.7rem; + color: green +} + +.product-panel .media img, +.ql-modal .media img { + max-width: 60px +} + +@media (max-width: 1200px) { + .ql-modal { + padding-left: 0 + } + .ql-modal .modal-dialog { + margin: 0 + } +} + +.wishlist { + background-color: #ff3547 +} + +.collection-card .stripe { + position: absolute; + bottom: 3rem; + width: 100%; + text-align: center; + padding: 1.2rem +} + +.collection-card .stripe.dark { + background-color: rgba(0, 0, 0, .7) +} + +.collection-card .stripe.dark a p { + color: #eee +} + +.collection-card .stripe.light { + background-color: rgba(255, 255, 255, .7) +} + +.collection-card .stripe.light a p { + color: #424242 +} + +.collection-card .stripe a p { + padding: 0; + margin: 0; + letter-spacing: 4px; + font-size: 1rem +} + +.cart-modal .table .total { + text-transform: uppercase; + font-weight: 600 +} + +.cart-modal .table .fa-remove { + color: #4285F4 +} + +.carousel-multi-item { + margin-bottom: 100px +} + +@media (min-width: 768px) { + .carousel-multi-item .col-md-4 { + float: left; + width: 33.333333%; + max-width: 100% + } +} + +.carousel-multi-item .carousel-item-next, +.carousel-multi-item .carousel-item-prev, +.carousel-multi-item .carousel-item.active { + display: block +} + +.carousel-multi-item .carousel-indicators li { + height: 20px; + max-width: 20px; + background-color: #4285F4; + margin-bottom: -60px +} + +.carousel-multi-item .carousel-indicators .active { + height: 25px; + max-width: 25px; + background-color: #4285F4; + border-radius: 50% +} + +.carousel-multi-item .controls-top { + margin-bottom: 30px +} + +.carousel-multi-item .controls-top .btn-floating { + background: #4285F4 +} + +.carousel-multi-item .carousel-indicators { + margin-bottom: -2em +} + +.carousel-multi-item .card { + margin: 1px +} + +.carousel-multi-item .card-cascade.narrower { + margin-top: 20px; + margin-bottom: 5px +} + +@media only screen and (max-width: 992px) { + .carousel-multi-item .carousel-indicators li { + margin-bottom: -30px + } +} + +.carousel-thumbnails { + margin-bottom: 80px +} + +.carousel-thumbnails .carousel-indicators { + margin-bottom: -75px; + position: absolute +} + +.carousel-thumbnails .carousel-indicators li { + height: auto; + max-width: 100px; + width: 100px; + border: none +} + +.carousel-thumbnails .carousel-indicators .active { + height: auto; + width: auto; + opacity: .5 +} + +.carousel-thumbnails .carousel-indicators img { + max-width: 100px; + height: 50px; + overflow: hidden; + display: block +} + +@media only screen and (max-width: 600px) { + .carousel-thumbnails { + margin-bottom: 60px + } + .carousel-thumbnails .carousel-indicators { + margin-bottom: -60px + } + .carousel-thumbnails .carousel-indicators img { + max-width: 50px; + height: 25px + } +} + +.stepper li a { + padding: 24px; + font-size: 14px +} + +.stepper li a .circle { + display: inline-block; + color: #fff; + border-radius: 50%; + background: rgba(0, 0, 0, .38); + width: 24px; + height: 24px; + line-height: 24px; + margin-right: 8px +} + +.stepper li a .label { + display: inline-block; + color: rgba(0, 0, 0, .38) +} + +.stepper-horizontal, +.stepper-horizontal li { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox +} + +.stepper li.active a .label, +.stepper li.completed a .label { + font-weight: 600; + color: rgba(0, 0, 0, .87) +} + +.stepper-horizontal { + position: relative; + display: flex; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between +} + +.stepper-horizontal li { + -webkit-transition: .5s; + transition: .5s; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.stepper-vertical, +.stepper-vertical li { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + position: relative +} + +.stepper-horizontal li a .label { + margin-top: 10px +} + +.stepper-horizontal li:not(:first-child):before, +.stepper-horizontal li:not(:last-child):after { + content: ''; + position: relative; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + margin: 8px 0 0; + height: 1px; + background-color: rgba(0, 0, 0, .1) +} + +.error404, +.stepper-vertical { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column +} + +.stepper-horizontal li:hover { + background: #ddd +} + +.stepper-vertical { + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between +} + +.stepper-vertical li { + display: flex; + -webkit-box-align: start; + -webkit-align-items: flex-start; + -ms-flex-align: start; + align-items: flex-start; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column +} + +.stepper-vertical li a { + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative +} + +.stepper-vertical li a .circle { + -webkit-box-ordinal-group: 2; + -webkit-order: 1; + -ms-flex-order: 1; + order: 1 +} + +.stepper-vertical li a .label { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-flow: column nowrap; + -ms-flex-flow: column nowrap; + flex-flow: column nowrap; + -webkit-box-ordinal-group: 3; + -webkit-order: 2; + -ms-flex-order: 2; + order: 2 +} + +.stepper-vertical li.completed a .label { + font-weight: 500 +} + +.stepper-vertical li .step-content { + display: block; + margin-top: 0; + margin-left: 50px; + padding: 15px +} + +.stepper-vertical li .step-content p { + font-size: .875rem +} + +.stepper-vertical li:not(:last-child):after { + content: " "; + position: absolute; + width: 1px; + height: -webkit-calc(100% - 40px); + height: calc(100% - 40px); + left: 35px; + top: 55px; + background-color: rgba(0, 0, 0, .1) +} + +.author-box { + padding: 3rem +} + +@media (max-width: 601px) { + .author-box { + text-align: center + } + .author-box img { + margin-bottom: 2rem; + display: inline + } +} + +.author-box strong { + font-weight: 600 +} + +.comments-list, +.reply-form { + margin-bottom: 3rem +} + +.comments-list ul, +.reply-form ul { + list-style-type: none +} + +.comments-list img, +.reply-form img { + max-width: 100px; + border-radius: 50% +} + +.comments-list .row, +.reply-form .row { + margin-bottom: 2rem +} + +.comments-list .user-name, +.reply-form .user-name { + color: #000 +} + +.comments-list .comment-date, +.reply-form .comment-date { + color: #666 +} + +.comments-list .comment-text, +.reply-form .comment-text { + color: #9e9e9e +} + +@media (max-width: 601px) { + .comments-list, + .reply-form { + text-align: center + } + .comments-list img, + .reply-form img { + display: inline; + margin-bottom: 1rem + } + .comments-list .md-form, + .reply-form .md-form { + text-align: left + } +} + +.comments-list .text-center, +.reply-form .text-center { + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.section-blog-fw h2 { + margin-bottom: 1rem +} + +.personal-sm { + margin-bottom: 10px +} + +.personal-sm a { + padding: 5px +} + +.personal-sm a:first-of-type { + padding-left: 0 +} + +.personal-sm a .fa { + -webkit-transition-duration: .2s; + transition-duration: .2s +} + +.personal-sm a:hover .fa { + -webkit-transform: scale(1.2); + -ms-transform: scale(1.2); + transform: scale(1.2) +} + +.toast-title { + font-weight: 700 +} + +.toast-message { + -ms-word-wrap: break-word; + word-wrap: break-word +} + +.toast-message a:hover { + color: #ccc; + text-decoration: none +} + +.white-skin .navbar .navbar-nav .nav-item a, +.white-skin .navbar.double-nav a, +.white-skin .side-nav .social a .fa { + color: #424242 +} + +.toast-close-button { + position: relative; + right: -.3em; + top: -.3em; + float: right; + font-size: 20px; + font-weight: 700; + -webkit-text-shadow: 0 1px 0 #fff; + text-shadow: 0 1px 0 #fff; + opacity: .8; + -ms-filter: progid: DXImageTransform.Microsoft.Alpha(Opacity=80); + filter: alpha(opacity=80) +} + +.toast-top-center, +.toast-top-full-width { + top: 0; + right: 0; + width: 100% +} + +.clockpicker-display .clockpicker-display-column, +.picker__date-display .clockpicker-display .clockpicker-display-column { + float: left +} + +.toast-close-button:focus, +.toast-close-button:hover { + text-decoration: none; + cursor: pointer; + opacity: .4; + -ms-filter: progid: DXImageTransform.Microsoft.Alpha(Opacity=40); + filter: alpha(opacity=40) +} + +button.toast-close-button { + padding: 0; + cursor: pointer; + background: 0 0; + border: 0; + -webkit-appearance: none +} + +.toast-bottom-center { + bottom: 0; + right: 0; + width: 100% +} + +.toast-bottom-full-width { + bottom: 0; + right: 0; + width: 100% +} + +.toast-top-left { + top: 12px; + left: 12px +} + +.toast-top-right { + top: 12px; + right: 12px +} + +.toast-bottom-right { + right: 12px; + bottom: 12px +} + +.toast-bottom-left { + bottom: 12px; + left: 12px +} + +#toast-container { + position: fixed; + z-index: 999999 +} + +#toast-container * { + -webkit-box-sizing: border-box; + box-sizing: border-box +} + +#toast-container>div { + position: relative; + overflow: hidden; + margin: 0 0 6px; + padding: 15px 15px 15px 50px; + width: 300px; + background-position: 15px center; + background-repeat: no-repeat; + opacity: .95; + -ms-filter: progid: DXImageTransform.Microsoft.Alpha(Opacity=95); + filter: alpha(opacity=95) +} + +#toast-container>:hover { + -webkit-transition: .45s; + transition: .45s; + -webkit-box-shadow: 0 8px 17px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19); + box-shadow: 0 8px 17px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19); + opacity: 1; + -ms-filter: progid: DXImageTransform.Microsoft.Alpha(Opacity=100); + filter: alpha(opacity=100); + cursor: pointer +} + +#toast-container.toast-bottom-center>div, +#toast-container.toast-top-center>div { + width: 300px; + margin: auto +} + +#toast-container.toast-bottom-full-width>div, +#toast-container.toast-top-full-width>div { + width: 96%; + margin: auto +} + +.toast { + background-color: #030303 +} + +.toast-success { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important +} + +.toast-error { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important +} + +.toast-info { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important +} + +.toast-warning { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important +} + +.toast-progress { + position: absolute; + left: 0; + bottom: 0; + height: 4px; + background-color: #000; + opacity: .4; + -ms-filter: progid: DXImageTransform.Microsoft.Alpha(Opacity=40); + filter: alpha(opacity=40) +} + +@media all and (max-width: 240px) { + #toast-container>div { + padding: 8px 8px 8px 50px; + width: 11em + } + #toast-container .toast-close-button { + right: -.2em; + top: -.2em + } +} + +@media all and (min-width: 241px) and (max-width:480px) { + #toast-container>div { + padding: 8px 8px 8px 50px; + width: 18em + } + #toast-container .toast-close-button { + right: -.2em; + top: -.2em + } +} + +@media all and (min-width: 481px) and (max-width:768px) { + #toast-container>div { + padding: 15px 15px 15px 50px; + width: 25em + } +} + +.collapsible .active .rotate-icon { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); + -webkit-transition: all 150ms ease-in 0s; + transition: all 150ms ease-in 0s +} + +.min-chart { + position: relative; + display: inline-block; + width: 110px; + height: 110px; + margin-top: 50px; + margin-bottom: 50px; + text-align: center +} + +.min-chart canvas { + position: absolute; + top: 0; + left: 0 +} + +.min-chart .percent { + display: inline-block; + line-height: 110px; + z-index: 2 +} + +.min-chart .percent:after { + content: '%'; + margin-left: .1em; + font-size: .8em +} + +.progress { + box-shadow: none; + position: relative; + display: block; + width: 100%; + height: 4px; + overflow: hidden; + margin-bottom: 1rem; + background-color: #eee +} + +.progress .progress-bar { + -webkit-box-shadow: none; + box-shadow: none; + height: 4px; + border-radius: 0; + background-color: #0d47a1 +} + +.progress .progress-bar-animated { + -webkit-transition: width 2s ease-in-out; + transition: width 2s ease-in-out +} + +.progress .indeterminate { + background-color: #90caf9 +} + +.progress .indeterminate:after, +.progress .indeterminate:before { + content: ''; + position: absolute; + background-color: inherit; + left: 0; + will-change: left, right; + top: 0; + bottom: 0 +} + +.progress .indeterminate:before { + -webkit-animation: indeterminate 2.1s cubic-bezier(.65, .815, .735, .395) infinite; + animation: indeterminate 2.1s cubic-bezier(.65, .815, .735, .395) infinite +} + +.progress .indeterminate:after { + -webkit-animation: indeterminate-short 2.1s cubic-bezier(.165, .84, .44, 1) infinite; + animation: indeterminate-short 2.1s cubic-bezier(.165, .84, .44, 1) infinite; + -webkit-animation-delay: 1.15s; + animation-delay: 1.15s +} + +@-webkit-keyframes indeterminate { + 0% { + left: -35%; + right: 100% + } + 100%, + 60% { + left: 100%; + right: -90% + } +} + +@keyframes indeterminate { + 0% { + left: -35%; + right: 100% + } + 100%, + 60% { + left: 100%; + right: -90% + } +} + +@-webkit-keyframes indeterminate-short { + 0% { + left: -200%; + right: 100% + } + 100%, + 60% { + left: 107%; + right: -8% + } +} + +@keyframes indeterminate-short { + 0% { + left: -200%; + right: 100% + } + 100%, + 60% { + left: 107%; + right: -8% + } +} + +.preloader-wrapper { + display: inline-block; + position: relative; + width: 48px; + height: 48px +} + +.preloader-wrapper.small { + width: 36px; + height: 36px +} + +.preloader-wrapper.big { + width: 64px; + height: 64px +} + +.preloader-wrapper.active { + -webkit-animation: container-rotate 1568ms linear infinite; + animation: container-rotate 1568ms linear infinite +} + +.preloader-wrapper.crazy { + -webkit-animation-duration: 333ms; + animation-duration: 333ms +} + +.preloader-wrapper .spinner-layer { + position: absolute; + width: 100%; + height: 100%; + opacity: 0 +} + +.preloader-wrapper .spinner-layer .gap-patch { + position: absolute; + top: 0; + left: 45%; + width: 10%; + height: 100%; + overflow: hidden; + border-color: inherit +} + +.preloader-wrapper .spinner-layer .gap-patch .circle { + width: 1000%; + left: -450% +} + +.preloader-wrapper .spinner-layer .circle-clipper { + display: inline-block; + position: relative; + width: 50%; + height: 100%; + overflow: hidden; + border-color: inherit +} + +.preloader-wrapper .spinner-layer .circle-clipper .circle { + width: 200%; + height: 100%; + border-width: 3px; + border-style: solid; + border-color: inherit; + border-bottom-color: transparent!important; + border-radius: 50%; + -webkit-animation: none; + animation: none; + position: absolute; + top: 0; + right: 0; + bottom: 0 +} + +.preloader-wrapper .spinner-layer .circle-clipper.left .circle { + left: 0; + border-right-color: transparent!important; + -webkit-transform: rotate(129deg); + -ms-transform: rotate(129deg); + transform: rotate(129deg) +} + +.preloader-wrapper .spinner-layer .circle-clipper.right .circle { + left: -100%; + border-left-color: transparent!important; + -webkit-transform: rotate(-129deg); + -ms-transform: rotate(-129deg); + transform: rotate(-129deg) +} + +.preloader-wrapper .spinner-blue, +.preloader-wrapper .spinner-blue-only { + border-color: #4285f4 +} + +.preloader-wrapper .spinner-red, +.preloader-wrapper .spinner-red-only { + border-color: #db4437 +} + +.preloader-wrapper .spinner-yellow, +.preloader-wrapper .spinner-yellow-only { + border-color: #f4b400 +} + +.preloader-wrapper .spinner-green, +.preloader-wrapper .spinner-green-only { + border-color: #0f9d58 +} + +@-webkit-keyframes container-rotate { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +@keyframes container-rotate { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +.active .spinner-layer.spinner-blue { + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(.4, 0, .2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(.4, 0, .2, 1) infinite both +} + +.active .spinner-layer.spinner-red { + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(.4, 0, .2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(.4, 0, .2, 1) infinite both +} + +.active .spinner-layer.spinner-yellow { + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(.4, 0, .2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(.4, 0, .2, 1) infinite both +} + +.active .spinner-layer.spinner-green { + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(.4, 0, .2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(.4, 0, .2, 1) infinite both +} + +.active .spinner-layer.spinner-blue-only, +.active .spinner-layer.spinner-green-only, +.active .spinner-layer.spinner-primary-color-only, +.active .spinner-layer.spinner-red-only, +.active .spinner-layer.spinner-yellow-only { + opacity: 1; + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(.4, 0, .2, 1) infinite both +} + +.active .circle-clipper.left .circle { + -webkit-animation: left-spin 1333ms cubic-bezier(.4, 0, .2, 1) infinite both; + animation: left-spin 1333ms cubic-bezier(.4, 0, .2, 1) infinite both +} + +.active .circle-clipper.right .circle { + -webkit-animation: right-spin 1333ms cubic-bezier(.4, 0, .2, 1) infinite both; + animation: right-spin 1333ms cubic-bezier(.4, 0, .2, 1) infinite both +} + +@-webkit-keyframes fill-unfill-rotate { + 12.5% { + -webkit-transform: rotate(135deg); + transform: rotate(135deg) + } + 25% { + -webkit-transform: rotate(270deg); + transform: rotate(270deg) + } + 37.5% { + -webkit-transform: rotate(405deg); + transform: rotate(405deg) + } + 50% { + -webkit-transform: rotate(540deg); + transform: rotate(540deg) + } + 62.5% { + -webkit-transform: rotate(675deg); + transform: rotate(675deg) + } + 75% { + -webkit-transform: rotate(810deg); + transform: rotate(810deg) + } + 87.5% { + -webkit-transform: rotate(945deg); + transform: rotate(945deg) + } + to { + -webkit-transform: rotate(1080deg); + transform: rotate(1080deg) + } +} + +@keyframes fill-unfill-rotate { + 12.5% { + -webkit-transform: rotate(135deg); + transform: rotate(135deg) + } + 25% { + -webkit-transform: rotate(270deg); + transform: rotate(270deg) + } + 37.5% { + -webkit-transform: rotate(405deg); + transform: rotate(405deg) + } + 50% { + -webkit-transform: rotate(540deg); + transform: rotate(540deg) + } + 62.5% { + -webkit-transform: rotate(675deg); + transform: rotate(675deg) + } + 75% { + -webkit-transform: rotate(810deg); + transform: rotate(810deg) + } + 87.5% { + -webkit-transform: rotate(945deg); + transform: rotate(945deg) + } + to { + -webkit-transform: rotate(1080deg); + transform: rotate(1080deg) + } +} + +@-webkit-keyframes blue-fade-in-out { + 100%, + 25%, + 90%, + from { + opacity: 1 + } + 26%, + 89% { + opacity: 0 + } +} + +@keyframes blue-fade-in-out { + 100%, + 25%, + 90%, + from { + opacity: 1 + } + 26%, + 89% { + opacity: 0 + } +} + +@-webkit-keyframes red-fade-in-out { + 15%, + 51%, + from { + opacity: 0 + } + 25%, + 50% { + opacity: 1 + } +} + +@keyframes red-fade-in-out { + 15%, + 51%, + from { + opacity: 0 + } + 25%, + 50% { + opacity: 1 + } +} + +@-webkit-keyframes yellow-fade-in-out { + 40%, + 76%, + from { + opacity: 0 + } + 50%, + 75% { + opacity: 1 + } +} + +@keyframes yellow-fade-in-out { + 40%, + 76%, + from { + opacity: 0 + } + 50%, + 75% { + opacity: 1 + } +} + +@-webkit-keyframes green-fade-in-out { + 100%, + 65%, + from { + opacity: 0 + } + 75%, + 90% { + opacity: 1 + } +} + +@keyframes green-fade-in-out { + 100%, + 65%, + from { + opacity: 0 + } + 75%, + 90% { + opacity: 1 + } +} + +@-webkit-keyframes left-spin { + from, + to { + -webkit-transform: rotate(130deg); + transform: rotate(130deg) + } + 50% { + -webkit-transform: rotate(-5deg); + transform: rotate(-5deg) + } +} + +@keyframes left-spin { + from, + to { + -webkit-transform: rotate(130deg); + transform: rotate(130deg) + } + 50% { + -webkit-transform: rotate(-5deg); + transform: rotate(-5deg) + } +} + +@-webkit-keyframes right-spin { + from, + to { + -webkit-transform: rotate(-130deg); + transform: rotate(-130deg) + } + 50% { + -webkit-transform: rotate(5deg); + transform: rotate(5deg) + } +} + +@keyframes right-spin { + from, + to { + -webkit-transform: rotate(-130deg); + transform: rotate(-130deg) + } + 50% { + -webkit-transform: rotate(5deg); + transform: rotate(5deg) + } +} + +#spinnerContainer.cooldown { + -webkit-animation: container-rotate 1568ms linear infinite, fade-out .4s cubic-bezier(.4, 0, .2, 1); + animation: container-rotate 1568ms linear infinite, fade-out .4s cubic-bezier(.4, 0, .2, 1) +} + +@-webkit-keyframes fade-out { + from { + opacity: 1 + } + to { + opacity: 0 + } +} + +@keyframes fade-out { + from { + opacity: 1 + } + to { + opacity: 0 + } +} + +#mdb-preloader { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #000; + z-index: 9998; + height: 100%; + width: 100% +} + +.ps { + -ms-touch-action: auto; + touch-action: auto; + overflow: hidden!important +} + +.ps.ps--active-x>.ps__scrollbar-x-rail, +.ps.ps--active-y>.ps__scrollbar-y-rail { + display: block; + background-color: transparent +} + +.ps.ps--active-y>.ps__scrollbar-y-rail { + top: 0!important +} + +.ps.ps--in-scrolling.ps--x>.ps__scrollbar-x-rail { + background-color: #eee; + opacity: .9 +} + +.ps.ps--in-scrolling.ps--x>.ps__scrollbar-x-rail>.ps__scrollbar-x { + background-color: #999; + height: 11px +} + +.ps>.ps__scrollbar-x-rail { + display: none; + position: absolute; + opacity: 0; + -webkit-transition: background-color .2s linear, opacity .2s linear; + transition: background-color .2s linear, opacity .2s linear; + bottom: 0; + height: 15px +} + +.ps>.ps__scrollbar-x-rail>.ps__scrollbar-x { + position: absolute; + background-color: #aaa; + border-radius: 6px; + -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + bottom: 2px; + height: 6px +} + +.ps>.ps__scrollbar-x-rail:hover>.ps__scrollbar-x, +.ps>.ps__scrollbar-x-rail>.ps__scrollbar-x-rail:active>.ps__scrollbar-x { + height: 11px +} + +.ps.ps--in-scrolling.ps--y>.ps__scrollbar-y-rail { + background-color: #eee; + opacity: .9 +} + +.ps.ps--in-scrolling.ps--y>.ps__scrollbar-y-rail>.ps__scrollbar-y { + background-color: #999; + width: 11px +} + +.ps>.ps__scrollbar-y-rail { + display: none; + position: absolute; + opacity: 0; + -webkit-transition: background-color .2s linear, opacity .2s linear; + transition: background-color .2s linear, opacity .2s linear; + right: 0; + width: 15px; + z-index: 999 +} + +.ps>.ps__scrollbar-y-rail>.ps__scrollbar-y { + position: absolute; + background-color: #aaa; + border-radius: 6px; + -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + right: 2px; + width: 6px +} + +.ps>.ps__scrollbar-y-rail:hover>.ps__scrollbar-y, +.ps>.ps__scrollbar-y-rail>.ps__scrollbar-y-rail:active>.ps__scrollbar-y { + width: 11px +} + +.ps:hover.ps--in-scrolling.ps--x>.ps__scrollbar-x-rail { + background-color: #eee; + opacity: .9 +} + +.ps:hover.ps--in-scrolling.ps--x>.ps__scrollbar-x-rail>.ps__scrollbar-x { + background-color: #999; + height: 11px +} + +.ps:hover.ps--in-scrolling.ps--y>.ps__scrollbar-y-rail { + background-color: #eee; + opacity: .9 +} + +.ps:hover.ps--in-scrolling.ps--y>.ps__scrollbar-y-rail>.ps__scrollbar-y { + background-color: #999; + width: 11px +} + +.ps:hover>.ps__scrollbar-x-rail, +.ps:hover>.ps__scrollbar-y-rail { + opacity: .6 +} + +.ps:hover>.ps__scrollbar-x-rail:hover { + background-color: #eee; + opacity: .9 +} + +.ps:hover>.ps__scrollbar-x-rail:hover>.ps__scrollbar-x { + background-color: #999 +} + +.ps:hover>.ps__scrollbar-y-rail:hover { + background-color: #eee; + opacity: .9 +} + +.ps:hover>.ps__scrollbar-y-rail:hover>.ps__scrollbar-y { + background-color: #999 +} + +.sn-bg-1 { + background-image: url(https://mdbootstrap.com/img/Photos/Others/sidenav1.jpg) +} + +.sn-bg-2 { + background-image: url(https://mdbootstrap.com/img/Photos/Others/sidenav2.jpg) +} + +.sn-bg-3 { + background-image: url(https://mdbootstrap.com/img/Photos/Others/sidenav3.jpg) +} + +.sn-bg-4 { + background-image: url(https://mdbootstrap.com/img/Photos/Others/sidenav4.jpg) +} + +.white-skin .gradient { + background: #ababab; + background: -webkit-linear-gradient(315deg, #ababab 0, #fff 100%); + background: linear-gradient(135deg, #ababab 0, #fff 100%) +} + +.stepper li.active a .white-skin .circle, +.stepper li.completed a .white-skin .circle, +.white-skin .primary-color, +.white-skin .stepper li.active a .circle, +.white-skin .stepper li.completed a .circle { + background-color: #4285F4!important +} + +.white-skin .navbar { + background-color: #fff; + color: #424242 +} + +.white-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.white-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.white-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #2a75f3 +} + +.white-skin .page-footer { + background-color: #6f7178 +} + +.white-skin .side-nav { + background-color: #F9F9F9 +} + +.white-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.white-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #0d5bdd +} + +.white-skin .side-nav .social a:hover .fa { + color: #4285F4!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.white-skin .side-nav .search-form input[type=text] { + color: #424242!important; + border-bottom: 1px solid rgba(153, 153, 153, .3) +} + +.white-skin .side-nav .search-form input[type=text]:-moz-placeholder { + color: rgba(66, 66, 66, .5)!important +} + +.white-skin .side-nav .search-form input[type=text]::-ms-placeholder { + color: rgba(66, 66, 66, .5)!important +} + +.white-skin .side-nav .search-form input[type=text]::-webkit-input-placeholder { + color: rgba(66, 66, 66, .5)!important +} + +.white-skin .side-nav .search-form input[type=text]::-moz-placeholder { + color: rgba(66, 66, 66, .5)!important +} + +.white-skin .side-nav .search-form input[type=text]:-ms-input-placeholder { + color: rgba(66, 66, 66, .5)!important +} + +.white-skin .side-nav .search-form input[type=text]::placeholder { + color: rgba(66, 66, 66, .5)!important +} + +.white-skin .side-nav .collapsible li { + background-color: transparent +} + +.white-skin .side-nav .collapsible li a { + font-weight: 400 +} + +.white-skin .side-nav .collapsible li .collapsible-header { + color: #424242; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.white-skin .side-nav .collapsible li .collapsible-header.active { + color: #4285F4; + background-color: transparent +} + +.white-skin .side-nav .collapsible a:hover, +.white-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(0, 0, 0, .05) +} + +.white-skin .side-nav .collapsible li .collapsible-body a { + color: #424242 +} + +.white-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #4285F4 +} + +.white-skin .side-nav .collapsible a { + color: #424242; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.white-skin .side-nav .fa { + color: #424242 +} + +.white-skin .dropdown-content li:not(.disabled) span, +.white-skin .md-form .prefix.active, +.white-skin input[type=email]:focus:not([readonly])+label, +.white-skin input[type=text]:focus:not([readonly])+label, +.white-skin input[type=password]:focus:not([readonly])+label, +.white-skin textarea.md-textarea:focus:not([readonly])+label { + color: #4285F4 +} + +.white-skin .side-nav .sidenav-bg.mask-strong:after, +.white-skin .side-nav .sidenav-bg:after { + background: rgba(255, 255, 255, .8) +} + +.white-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(255, 255, 255, .65) +} + +.white-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(255, 255, 255, .5) +} + +.white-skin .btn-primary { + background-color: #4285F4 +} + +.white-skin .btn-primary:hover { + background-color: #5a95f5!important +} + +.white-skin .btn-primary.active, +.white-skin .btn-primary:active, +.white-skin .btn-primary:focus { + background-color: #0d5bdd!important +} + +.white-skin .btn-primary.dropdown-toggle { + background-color: #4285F4!important +} + +.white-skin .btn-primary.dropdown-toggle:focus, +.white-skin .btn-primary.dropdown-toggle:hover { + background-color: #5a95f5!important +} + +.white-skin .btn-secondary { + background-color: #fc685f +} + +.white-skin .btn-secondary:hover { + background-color: #fc8078!important +} + +.white-skin .btn-secondary.active, +.white-skin .btn-secondary:active, +.white-skin .btn-secondary:focus { + background-color: #fb2114!important +} + +.white-skin .btn-secondary.dropdown-toggle { + background-color: #fc685f!important +} + +.white-skin .btn-secondary.dropdown-toggle:focus, +.white-skin .btn-secondary.dropdown-toggle:hover { + background-color: #fc8078!important +} + +.white-skin .btn-default { + background-color: #454545 +} + +.white-skin .btn-default:hover { + background-color: #525252!important +} + +.white-skin .btn-default.active, +.white-skin .btn-default:active, +.white-skin .btn-default:focus { + background-color: #1f1f1f!important +} + +.white-skin .btn-default.dropdown-toggle { + background-color: #454545!important +} + +.white-skin .btn-default.dropdown-toggle:focus, +.white-skin .btn-default.dropdown-toggle:hover { + background-color: #525252!important +} + +.white-skin .card .btn-action { + background: #454545 +} + +.white-skin .card .btn-action:focus, +.white-skin .card .btn-action:hover { + background-color: #525252!important +} + +.white-skin .card .btn-action.active { + background-color: #121212!important +} + +.white-skin input[type=email]:focus:not([readonly]), +.white-skin input[type=text]:focus:not([readonly]), +.white-skin input[type=password]:focus:not([readonly]), +.white-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #4285F4; + -webkit-box-shadow: 0 1px 0 0 #4285F4; + box-shadow: 0 1px 0 0 #4285F4 +} + +.white-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #4285F4; + border-bottom: 2px solid #4285F4 +} + +.white-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.white-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #4285F4; + border-color: #4285F4 +} + +.white-skin .top-nav-collapse { + background-color: #fff +} + +.white-skin .carousel-multi-item .carousel-indicators li, +.white-skin .carousel-multi-item .carousel-indicators li.active, +.white-skin .carousel-multi-item .controls-top>a { + background-color: #4285F4 +} + +.white-skin .card-header, +.white-skin .form-header { + background-color: #4c8bf5 +} + +.white-skin .spinner-primary-color, +.white-skin .spinner-primary-color-only { + border-color: #4285F4 +} + +.white-skin .pagination-primary-color .page-item.active .page-link, +.white-skin .pagination-primary-color .page-item.active .page-link:focus, +.white-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #4285F4; + border-color: #4285F4 +} + +.white-skin .pagination-primary-color .page-link { + color: #4285F4 +} + +.black-skin .gradient { + background: #000; + background: -webkit-linear-gradient(315deg, #000 0, #616161 100%); + background: linear-gradient(135deg, #000 0, #616161 100%) +} + +.black-skin .primary-color, +.black-skin .stepper li.active a .circle, +.black-skin .stepper li.completed a .circle, +.stepper li.active a .black-skin .circle, +.stepper li.completed a .black-skin .circle { + background-color: #2AD1A3!important +} + +.black-skin .navbar { + background-color: #222; + color: #fff +} + +.black-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.black-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.black-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #26bc92 +} + +.black-skin .page-footer, +.black-skin .side-nav { + background-color: #222 +} + +.black-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.black-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #1d9171 +} + +.black-skin .side-nav .social a:hover .fa { + color: #2AD1A3!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.black-skin .side-nav .collapsible li { + background-color: transparent +} + +.black-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.black-skin .side-nav .collapsible li .collapsible-header.active, +.black-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: #2AD1A3 +} + +.black-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.black-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #2AD1A3 +} + +.black-skin .side-nav .fa { + color: #fff +} + +.black-skin .dropdown-content li:not(.disabled) span, +.black-skin .md-form .prefix.active, +.black-skin input[type=email]:focus:not([readonly])+label, +.black-skin input[type=text]:focus:not([readonly])+label, +.black-skin input[type=password]:focus:not([readonly])+label, +.black-skin textarea.md-textarea:focus:not([readonly])+label { + color: #2AD1A3 +} + +.black-skin .side-nav .sidenav-bg.mask-strong:after, +.black-skin .side-nav .sidenav-bg:after { + background: rgba(0, 0, 0, .8) +} + +.black-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(0, 0, 0, .65) +} + +.black-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(0, 0, 0, .5) +} + +.black-skin .btn-primary { + background-color: #2AD1A3 +} + +.black-skin .btn-primary:hover { + background-color: #3dd8ad!important +} + +.black-skin .btn-primary.active, +.black-skin .btn-primary:active, +.black-skin .btn-primary:focus { + background-color: #1d9171!important +} + +.black-skin .btn-primary.dropdown-toggle { + background-color: #2AD1A3!important +} + +.black-skin .btn-primary.dropdown-toggle:focus, +.black-skin .btn-primary.dropdown-toggle:hover { + background-color: #3dd8ad!important +} + +.black-skin .btn-secondary { + background-color: #0f478a +} + +.black-skin .btn-secondary:hover { + background-color: #1253a1!important +} + +.black-skin .btn-secondary.active, +.black-skin .btn-secondary:active, +.black-skin .btn-secondary:focus { + background-color: #082445!important +} + +.black-skin .btn-secondary.dropdown-toggle { + background-color: #0f478a!important +} + +.black-skin .btn-secondary.dropdown-toggle:focus, +.black-skin .btn-secondary.dropdown-toggle:hover { + background-color: #1253a1!important +} + +.black-skin .btn-default { + background-color: #222 +} + +.black-skin .btn-default:hover { + background-color: #2f2f2f!important +} + +.black-skin .btn-default.active, +.black-skin .btn-default:active, +.black-skin .btn-default:focus { + background-color: #000!important +} + +.black-skin .btn-default.dropdown-toggle { + background-color: #222!important +} + +.black-skin .btn-default.dropdown-toggle:focus, +.black-skin .btn-default.dropdown-toggle:hover { + background-color: #2f2f2f!important +} + +.black-skin .card .btn-action { + background: #222 +} + +.black-skin .card .btn-action:focus, +.black-skin .card .btn-action:hover { + background-color: #2f2f2f!important +} + +.black-skin .card .btn-action.active { + background-color: #000!important +} + +.black-skin input[type=email]:focus:not([readonly]), +.black-skin input[type=text]:focus:not([readonly]), +.black-skin input[type=password]:focus:not([readonly]), +.black-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #2AD1A3; + -webkit-box-shadow: 0 1px 0 0 #2AD1A3; + box-shadow: 0 1px 0 0 #2AD1A3 +} + +.black-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #2AD1A3; + border-bottom: 2px solid #2AD1A3 +} + +.black-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.black-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #2AD1A3; + border-color: #2AD1A3 +} + +.black-skin .top-nav-collapse { + background-color: #222 +} + +.black-skin .carousel-multi-item .carousel-indicators li, +.black-skin .carousel-multi-item .carousel-indicators li.active, +.black-skin .carousel-multi-item .controls-top>a { + background-color: #2AD1A3 +} + +.black-skin .card-header, +.black-skin .form-header { + background-color: #30d5a8 +} + +.black-skin .spinner-primary-color, +.black-skin .spinner-primary-color-only { + border-color: #2AD1A3 +} + +.black-skin .pagination-primary-color .page-item.active .page-link, +.black-skin .pagination-primary-color .page-item.active .page-link:focus, +.black-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #2AD1A3; + border-color: #2AD1A3 +} + +.black-skin .pagination-primary-color .page-link { + color: #2AD1A3 +} + +.cyan-skin .gradient { + background: #114861; + background: -webkit-linear-gradient(315deg, #114861 0, #45b0c0 100%); + background: linear-gradient(135deg, #114861 0, #45b0c0 100%) +} + +.cyan-skin .primary-color, +.cyan-skin .stepper li.active a .circle, +.cyan-skin .stepper li.completed a .circle, +.stepper li.active a .cyan-skin .circle, +.stepper li.completed a .cyan-skin .circle { + background-color: #4fada7!important +} + +.cyan-skin .navbar { + background-color: #114861; + color: #fff +} + +.cyan-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.cyan-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.cyan-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #eea82f +} + +.cyan-skin .page-footer { + background-color: #114861 +} + +.cyan-skin .side-nav { + background-color: #24879d +} + +.cyan-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.cyan-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #d99012 +} + +.cyan-skin .side-nav .social a:hover .fa { + color: #f0b247!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.cyan-skin .side-nav .collapsible li { + background-color: transparent +} + +.cyan-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.cyan-skin .side-nav .collapsible li .collapsible-header.active, +.cyan-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(29, 65, 82, .8) +} + +.cyan-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.cyan-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #ffa742 +} + +.cyan-skin .side-nav .fa { + color: #fff +} + +.cyan-skin .dropdown-content li:not(.disabled) span, +.cyan-skin .md-form .prefix.active, +.cyan-skin input[type=email]:focus:not([readonly])+label, +.cyan-skin input[type=text]:focus:not([readonly])+label, +.cyan-skin input[type=password]:focus:not([readonly])+label, +.cyan-skin textarea.md-textarea:focus:not([readonly])+label { + color: #f0b247 +} + +.cyan-skin .side-nav .sidenav-bg.mask-strong:after, +.cyan-skin .side-nav .sidenav-bg:after { + background: rgba(21, 78, 96, .8) +} + +.cyan-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(21, 78, 96, .65) +} + +.cyan-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(21, 78, 96, .5) +} + +.cyan-skin .btn-primary { + background-color: #ffa742 +} + +.cyan-skin .btn-primary:hover { + background-color: #ffb35c!important +} + +.cyan-skin .btn-primary.active, +.cyan-skin .btn-primary:active, +.cyan-skin .btn-primary:focus { + background-color: #f58300!important +} + +.cyan-skin .btn-primary.dropdown-toggle { + background-color: #ffa742!important +} + +.cyan-skin .btn-primary.dropdown-toggle:focus, +.cyan-skin .btn-primary.dropdown-toggle:hover { + background-color: #ffb35c!important +} + +.cyan-skin .btn-secondary { + background-color: #45b0c0 +} + +.cyan-skin .btn-secondary:hover { + background-color: #58b8c6!important +} + +.cyan-skin .btn-secondary.active, +.cyan-skin .btn-secondary:active, +.cyan-skin .btn-secondary:focus { + background-color: #2f7e8a!important +} + +.cyan-skin .btn-secondary.dropdown-toggle { + background-color: #45b0c0!important +} + +.cyan-skin .btn-secondary.dropdown-toggle:focus, +.cyan-skin .btn-secondary.dropdown-toggle:hover { + background-color: #58b8c6!important +} + +.cyan-skin .btn-default { + background-color: #114861 +} + +.cyan-skin .btn-default:hover { + background-color: #155877!important +} + +.cyan-skin .btn-default.active, +.cyan-skin .btn-default:active, +.cyan-skin .btn-default:focus { + background-color: #061820!important +} + +.cyan-skin .btn-default.dropdown-toggle { + background-color: #114861!important +} + +.cyan-skin .btn-default.dropdown-toggle:focus, +.cyan-skin .btn-default.dropdown-toggle:hover { + background-color: #155877!important +} + +.cyan-skin .card .btn-action { + background: #114861 +} + +.cyan-skin .card .btn-action:focus, +.cyan-skin .card .btn-action:hover { + background-color: #155877!important +} + +.cyan-skin .card .btn-action.active { + background-color: #02080a!important +} + +.cyan-skin input[type=email]:focus:not([readonly]), +.cyan-skin input[type=text]:focus:not([readonly]), +.cyan-skin input[type=password]:focus:not([readonly]), +.cyan-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #f0b247; + -webkit-box-shadow: 0 1px 0 0 #f0b247; + box-shadow: 0 1px 0 0 #f0b247 +} + +.cyan-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #f0b247; + border-bottom: 2px solid #f0b247 +} + +.cyan-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.cyan-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #f0b247; + border-color: #f0b247 +} + +.cyan-skin .top-nav-collapse { + background-color: #114861 +} + +.cyan-skin .carousel-multi-item .carousel-indicators li, +.cyan-skin .carousel-multi-item .carousel-indicators li.active, +.cyan-skin .carousel-multi-item .controls-top>a { + background-color: #f0b247 +} + +.cyan-skin .card-header, +.cyan-skin .form-header { + background-color: #f1b650 +} + +.cyan-skin .spinner-primary-color, +.cyan-skin .spinner-primary-color-only { + border-color: #4fada7 +} + +.cyan-skin .pagination-primary-color .page-item.active .page-link, +.cyan-skin .pagination-primary-color .page-item.active .page-link:focus, +.cyan-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #4fada7; + border-color: #4fada7 +} + +.cyan-skin .pagination-primary-color .page-link { + color: #4fada7 +} + +.mdb-skin .gradient { + background: #0e2135; + background: -webkit-linear-gradient(315deg, #0e2135 0, #2c76b8 100%); + background: linear-gradient(135deg, #0e2135 0, #2c76b8 100%) +} + +.mdb-skin .primary-color, +.mdb-skin .stepper li.active a .circle, +.mdb-skin .stepper li.completed a .circle, +.stepper li.active a .mdb-skin .circle, +.stepper li.completed a .mdb-skin .circle { + background-color: #33b5e5!important +} + +.mdb-skin .navbar { + background-color: #243a51; + color: #fff +} + +.mdb-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.mdb-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.mdb-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #1dade2 +} + +.mdb-skin .page-footer { + background-color: #243a51 +} + +.mdb-skin .side-nav { + background-color: #224562 +} + +.mdb-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.mdb-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #178ab4 +} + +.mdb-skin .side-nav .social a:hover .fa { + color: #33b5e5!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.mdb-skin .side-nav .collapsible li { + background-color: transparent +} + +.mdb-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.mdb-skin .side-nav .collapsible li .collapsible-header.active, +.mdb-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(72, 198, 255, .8) +} + +.mdb-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.mdb-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #67d5ff +} + +.mdb-skin .side-nav .fa { + color: #fff +} + +.mdb-skin .dropdown-content li:not(.disabled) span, +.mdb-skin .md-form .prefix.active, +.mdb-skin input[type=email]:focus:not([readonly])+label, +.mdb-skin input[type=text]:focus:not([readonly])+label, +.mdb-skin input[type=password]:focus:not([readonly])+label, +.mdb-skin textarea.md-textarea:focus:not([readonly])+label { + color: #33b5e5 +} + +.mdb-skin .side-nav .sidenav-bg.mask-strong:after, +.mdb-skin .side-nav .sidenav-bg:after { + background: rgba(13, 36, 60, .8) +} + +.mdb-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(13, 36, 60, .65) +} + +.mdb-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(13, 36, 60, .5) +} + +.mdb-skin .btn-primary { + background-color: #33b5e5 +} + +.mdb-skin .btn-primary:hover { + background-color: #4abde8!important +} + +.mdb-skin .btn-primary.active, +.mdb-skin .btn-primary:active, +.mdb-skin .btn-primary:focus { + background-color: #178ab4!important +} + +.mdb-skin .btn-primary.dropdown-toggle { + background-color: #33b5e5!important +} + +.mdb-skin .btn-primary.dropdown-toggle:focus, +.mdb-skin .btn-primary.dropdown-toggle:hover { + background-color: #4abde8!important +} + +.mdb-skin .btn-secondary { + background-color: #0e3d67 +} + +.mdb-skin .btn-secondary:hover { + background-color: #114a7d!important +} + +.mdb-skin .btn-secondary.active, +.mdb-skin .btn-secondary:active, +.mdb-skin .btn-secondary:focus { + background-color: #051524!important +} + +.mdb-skin .btn-secondary.dropdown-toggle { + background-color: #0e3d67!important +} + +.mdb-skin .btn-secondary.dropdown-toggle:focus, +.mdb-skin .btn-secondary.dropdown-toggle:hover { + background-color: #114a7d!important +} + +.mdb-skin .btn-default { + background-color: #1a6398 +} + +.mdb-skin .btn-default:hover { + background-color: #1e71ae!important +} + +.mdb-skin .btn-default.active, +.mdb-skin .btn-default:active, +.mdb-skin .btn-default:focus { + background-color: #0f3857!important +} + +.mdb-skin .btn-default.dropdown-toggle { + background-color: #1a6398!important +} + +.mdb-skin .btn-default.dropdown-toggle:focus, +.mdb-skin .btn-default.dropdown-toggle:hover { + background-color: #1e71ae!important +} + +.mdb-skin .card .btn-action { + background: #1a6398 +} + +.mdb-skin .card .btn-action:focus, +.mdb-skin .card .btn-action:hover { + background-color: #1e71ae!important +} + +.mdb-skin .card .btn-action.active { + background-color: #0b2a41!important +} + +.mdb-skin input[type=email]:focus:not([readonly]), +.mdb-skin input[type=text]:focus:not([readonly]), +.mdb-skin input[type=password]:focus:not([readonly]), +.mdb-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #33b5e5; + -webkit-box-shadow: 0 1px 0 0 #33b5e5; + box-shadow: 0 1px 0 0 #33b5e5 +} + +.mdb-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #33b5e5; + border-bottom: 2px solid #33b5e5 +} + +.mdb-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.mdb-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #33b5e5; + border-color: #33b5e5 +} + +.mdb-skin .top-nav-collapse, +.mdb-skin-custom .navbar { + background-color: #243a51 +} + +.mdb-skin .carousel-multi-item .carousel-indicators li, +.mdb-skin .carousel-multi-item .carousel-indicators li.active, +.mdb-skin .carousel-multi-item .controls-top>a { + background-color: #33b5e5 +} + +.mdb-skin .card-header, +.mdb-skin .form-header { + background-color: #3cb8e6 +} + +.mdb-skin .spinner-primary-color, +.mdb-skin .spinner-primary-color-only { + border-color: #33b5e5 +} + +.mdb-skin .pagination-primary-color .page-item.active .page-link, +.mdb-skin .pagination-primary-color .page-item.active .page-link:focus, +.mdb-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #33b5e5; + border-color: #33b5e5 +} + +.mdb-skin .pagination-primary-color .page-link { + color: #33b5e5 +} + +.deep-purple-skin .gradient { + background: #2e1f49; + background: -webkit-linear-gradient(315deg, #2e1f49 0, #a47fe3 100%); + background: linear-gradient(135deg, #2e1f49 0, #a47fe3 100%) +} + +.deep-purple-skin .primary-color, +.deep-purple-skin .stepper li.active a .circle, +.deep-purple-skin .stepper li.completed a .circle, +.stepper li.active a .deep-purple-skin .circle, +.stepper li.completed a .deep-purple-skin .circle { + background-color: #d0637c!important +} + +.deep-purple-skin .navbar { + background-color: #7f7e91; + color: #fff +} + +.deep-purple-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.deep-purple-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.deep-purple-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #9d6eed +} + +.deep-purple-skin .page-footer { + background-color: #7f7e91 +} + +.deep-purple-skin .side-nav { + background-color: #372e5f +} + +.deep-purple-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.deep-purple-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #7e41e8 +} + +.deep-purple-skin .side-nav .social a:hover .fa { + color: #ac85f0!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.deep-purple-skin .side-nav .collapsible li { + background-color: transparent +} + +.deep-purple-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.deep-purple-skin .side-nav .collapsible li .collapsible-header.active, +.deep-purple-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(176, 139, 240, .5) +} + +.deep-purple-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.deep-purple-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #c9abfc +} + +.deep-purple-skin .side-nav .fa { + color: #fff +} + +.deep-purple-skin .dropdown-content li:not(.disabled) span, +.deep-purple-skin .md-form .prefix.active, +.deep-purple-skin input[type=email]:focus:not([readonly])+label, +.deep-purple-skin input[type=text]:focus:not([readonly])+label, +.deep-purple-skin input[type=password]:focus:not([readonly])+label, +.deep-purple-skin textarea.md-textarea:focus:not([readonly])+label { + color: #ac85f0 +} + +.deep-purple-skin .side-nav .sidenav-bg.mask-strong:after, +.deep-purple-skin .side-nav .sidenav-bg:after { + background: rgba(36, 9, 56, .88) +} + +.deep-purple-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(36, 9, 56, .65) +} + +.deep-purple-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(36, 9, 56, .5) +} + +.deep-purple-skin .btn-primary { + background-color: #ac85f0 +} + +.deep-purple-skin .btn-primary:hover { + background-color: #bb9cf3!important +} + +.deep-purple-skin .btn-primary.active, +.deep-purple-skin .btn-primary:active, +.deep-purple-skin .btn-primary:focus { + background-color: #7e41e8!important +} + +.deep-purple-skin .btn-primary.dropdown-toggle { + background-color: #ac85f0!important +} + +.deep-purple-skin .btn-primary.dropdown-toggle:focus, +.deep-purple-skin .btn-primary.dropdown-toggle:hover { + background-color: #bb9cf3!important +} + +.deep-purple-skin .btn-secondary { + background-color: #6e4ca3 +} + +.deep-purple-skin .btn-secondary:hover { + background-color: #7a58b1!important +} + +.deep-purple-skin .btn-secondary.active, +.deep-purple-skin .btn-secondary:active, +.deep-purple-skin .btn-secondary:focus { + background-color: #4b346f!important +} + +.deep-purple-skin .btn-secondary.dropdown-toggle { + background-color: #6e4ca3!important +} + +.deep-purple-skin .btn-secondary.dropdown-toggle:focus, +.deep-purple-skin .btn-secondary.dropdown-toggle:hover { + background-color: #7a58b1!important +} + +.deep-purple-skin .btn-default { + background-color: #372e5f +} + +.deep-purple-skin .btn-default:hover { + background-color: #413670!important +} + +.deep-purple-skin .btn-default.active, +.deep-purple-skin .btn-default:active, +.deep-purple-skin .btn-default:focus { + background-color: #19152b!important +} + +.deep-purple-skin .btn-default.dropdown-toggle { + background-color: #372e5f!important +} + +.deep-purple-skin .btn-default.dropdown-toggle:focus, +.deep-purple-skin .btn-default.dropdown-toggle:hover { + background-color: #413670!important +} + +.deep-purple-skin .card .btn-action { + background: #372e5f +} + +.deep-purple-skin .card .btn-action:focus, +.deep-purple-skin .card .btn-action:hover { + background-color: #413670!important +} + +.deep-purple-skin .card .btn-action.active { + background-color: #0f0d1a!important +} + +.deep-purple-skin input[type=email]:focus:not([readonly]), +.deep-purple-skin input[type=text]:focus:not([readonly]), +.deep-purple-skin input[type=password]:focus:not([readonly]), +.deep-purple-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #ac85f0; + -webkit-box-shadow: 0 1px 0 0 #ac85f0; + box-shadow: 0 1px 0 0 #ac85f0 +} + +.deep-purple-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #ac85f0; + border-bottom: 2px solid #ac85f0 +} + +.deep-purple-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.deep-purple-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #ac85f0; + border-color: #ac85f0 +} + +.deep-purple-skin .top-nav-collapse { + background-color: #7f7e91 +} + +.deep-purple-skin .carousel-multi-item .carousel-indicators li, +.deep-purple-skin .carousel-multi-item .carousel-indicators li.active, +.deep-purple-skin .carousel-multi-item .controls-top>a { + background-color: #ac85f0 +} + +.deep-purple-skin .card-header, +.deep-purple-skin .form-header { + background-color: #b28ef1 +} + +.deep-purple-skin .spinner-primary-color, +.deep-purple-skin .spinner-primary-color-only { + border-color: #d0637c +} + +.deep-purple-skin .pagination-primary-color .page-item.active .page-link, +.deep-purple-skin .pagination-primary-color .page-item.active .page-link:focus, +.deep-purple-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #d0637c; + border-color: #d0637c +} + +.deep-purple-skin .pagination-primary-color .page-link { + color: #d0637c +} + +.navy-blue-skin .gradient { + background: #222735; + background: -webkit-linear-gradient(315deg, #222735 0, #4f68a6 100%); + background: linear-gradient(135deg, #222735 0, #4f68a6 100%) +} + +.navy-blue-skin .primary-color, +.navy-blue-skin .stepper li.active a .circle, +.navy-blue-skin .stepper li.completed a .circle, +.stepper li.active a .navy-blue-skin .circle, +.stepper li.completed a .navy-blue-skin .circle { + background-color: #309e9e!important +} + +.navy-blue-skin .navbar { + background-color: #353b50; + color: #fff +} + +.navy-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.navy-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.navy-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #36b6b6 +} + +.navy-blue-skin .page-footer { + background-color: #353b50 +} + +.navy-blue-skin .side-nav { + background-color: #4c5678 +} + +.navy-blue-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.navy-blue-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #2b8f8f +} + +.navy-blue-skin .side-nav .social a:hover .fa { + color: #40c6c6!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.navy-blue-skin .side-nav .collapsible li { + background-color: transparent +} + +.navy-blue-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.navy-blue-skin .side-nav .collapsible li .collapsible-header.active, +.navy-blue-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(37, 207, 207, .8) +} + +.navy-blue-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.navy-blue-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #40c6c6 +} + +.navy-blue-skin .side-nav .fa { + color: #fff +} + +.navy-blue-skin .dropdown-content li:not(.disabled) span, +.navy-blue-skin .md-form .prefix.active, +.navy-blue-skin input[type=email]:focus:not([readonly])+label, +.navy-blue-skin input[type=text]:focus:not([readonly])+label, +.navy-blue-skin input[type=password]:focus:not([readonly])+label, +.navy-blue-skin textarea.md-textarea:focus:not([readonly])+label { + color: #40c6c6 +} + +.navy-blue-skin .side-nav .sidenav-bg.mask-strong:after, +.navy-blue-skin .side-nav .sidenav-bg:after { + background: rgba(14, 15, 32, .8) +} + +.navy-blue-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(14, 15, 32, .65) +} + +.navy-blue-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(14, 15, 32, .5) +} + +.navy-blue-skin .btn-primary { + background-color: #40c6c6 +} + +.navy-blue-skin .btn-primary:hover { + background-color: #54cccc!important +} + +.navy-blue-skin .btn-primary.active, +.navy-blue-skin .btn-primary:active, +.navy-blue-skin .btn-primary:focus { + background-color: #2b8f8f!important +} + +.navy-blue-skin .btn-primary.dropdown-toggle { + background-color: #40c6c6!important +} + +.navy-blue-skin .btn-primary.dropdown-toggle:focus, +.navy-blue-skin .btn-primary.dropdown-toggle:hover { + background-color: #54cccc!important +} + +.navy-blue-skin .btn-secondary { + background-color: #7e51b4 +} + +.navy-blue-skin .btn-secondary:hover { + background-color: #8b63bc!important +} + +.navy-blue-skin .btn-secondary.active, +.navy-blue-skin .btn-secondary:active, +.navy-blue-skin .btn-secondary:focus { + background-color: #593881!important +} + +.navy-blue-skin .btn-secondary.dropdown-toggle { + background-color: #7e51b4!important +} + +.navy-blue-skin .btn-secondary.dropdown-toggle:focus, +.navy-blue-skin .btn-secondary.dropdown-toggle:hover { + background-color: #8b63bc!important +} + +.navy-blue-skin .btn-default { + background-color: #293756 +} + +.navy-blue-skin .btn-default:hover { + background-color: #314267!important +} + +.navy-blue-skin .btn-default.active, +.navy-blue-skin .btn-default:active, +.navy-blue-skin .btn-default:focus { + background-color: #101622!important +} + +.navy-blue-skin .btn-default.dropdown-toggle { + background-color: #293756!important +} + +.navy-blue-skin .btn-default.dropdown-toggle:focus, +.navy-blue-skin .btn-default.dropdown-toggle:hover { + background-color: #314267!important +} + +.navy-blue-skin .card .btn-action { + background: #293756 +} + +.navy-blue-skin .card .btn-action:focus, +.navy-blue-skin .card .btn-action:hover { + background-color: #314267!important +} + +.navy-blue-skin .card .btn-action.active { + background-color: #080b11!important +} + +.navy-blue-skin input[type=email]:focus:not([readonly]), +.navy-blue-skin input[type=text]:focus:not([readonly]), +.navy-blue-skin input[type=password]:focus:not([readonly]), +.navy-blue-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #40c6c6; + -webkit-box-shadow: 0 1px 0 0 #40c6c6; + box-shadow: 0 1px 0 0 #40c6c6 +} + +.navy-blue-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #40c6c6; + border-bottom: 2px solid #40c6c6 +} + +.navy-blue-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.navy-blue-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #40c6c6; + border-color: #40c6c6 +} + +.navy-blue-skin .top-nav-collapse { + background-color: #353b50 +} + +.navy-blue-skin .carousel-multi-item .carousel-indicators li, +.navy-blue-skin .carousel-multi-item .carousel-indicators li.active, +.navy-blue-skin .carousel-multi-item .controls-top>a { + background-color: #40c6c6 +} + +.navy-blue-skin .card-header, +.navy-blue-skin .form-header { + background-color: #48c8c8 +} + +.navy-blue-skin .spinner-primary-color, +.navy-blue-skin .spinner-primary-color-only { + border-color: #309e9e +} + +.navy-blue-skin .pagination-primary-color .page-item.active .page-link, +.navy-blue-skin .pagination-primary-color .page-item.active .page-link:focus, +.navy-blue-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #309e9e; + border-color: #309e9e +} + +.navy-blue-skin .pagination-primary-color .page-link { + color: #309e9e +} + +.pink-skin .gradient { + background: #812b5a; + background: -webkit-linear-gradient(315deg, #812b5a 0, #f28cc0 100%); + background: linear-gradient(135deg, #812b5a 0, #f28cc0 100%) +} + +.pink-skin .primary-color, +.pink-skin .stepper li.active a .circle, +.pink-skin .stepper li.completed a .circle, +.stepper li.active a .pink-skin .circle, +.stepper li.completed a .pink-skin .circle { + background-color: #bd5d70!important +} + +.pink-skin .navbar { + background-color: #535466; + color: #fff +} + +.pink-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.pink-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.pink-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #9192a2 +} + +.pink-skin .page-footer { + background-color: #535466 +} + +.pink-skin .side-nav { + background-color: #aa5077 +} + +.pink-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.pink-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #76778b +} + +.pink-skin .side-nav .social a:hover .fa { + color: #9fa0ae!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.pink-skin .side-nav .collapsible li { + background-color: transparent +} + +.pink-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.pink-skin .side-nav .collapsible li .collapsible-header.active, +.pink-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(0, 0, 0, .4) +} + +.pink-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.pink-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #ffb0e6 +} + +.pink-skin .side-nav .fa { + color: #fff +} + +.pink-skin .dropdown-content li:not(.disabled) span, +.pink-skin .md-form .prefix.active, +.pink-skin input[type=email]:focus:not([readonly])+label, +.pink-skin input[type=text]:focus:not([readonly])+label, +.pink-skin input[type=password]:focus:not([readonly])+label, +.pink-skin textarea.md-textarea:focus:not([readonly])+label { + color: #9fa0ae +} + +.pink-skin .side-nav .sidenav-bg.mask-strong:after, +.pink-skin .side-nav .sidenav-bg:after { + background: rgba(152, 47, 88, .8) +} + +.pink-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(152, 47, 88, .65) +} + +.pink-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(152, 47, 88, .5) +} + +.pink-skin .btn-primary { + background-color: #601f39 +} + +.pink-skin .btn-primary:hover { + background-color: #732544!important +} + +.pink-skin .btn-primary.active, +.pink-skin .btn-primary:active, +.pink-skin .btn-primary:focus { + background-color: #260c17!important +} + +.pink-skin .btn-primary.dropdown-toggle { + background-color: #601f39!important +} + +.pink-skin .btn-primary.dropdown-toggle:focus, +.pink-skin .btn-primary.dropdown-toggle:hover { + background-color: #732544!important +} + +.pink-skin .btn-secondary { + background-color: #e7649d +} + +.pink-skin .btn-secondary:hover { + background-color: #ea7aab!important +} + +.pink-skin .btn-secondary.active, +.pink-skin .btn-secondary:active, +.pink-skin .btn-secondary:focus { + background-color: #dc2273!important +} + +.pink-skin .btn-secondary.dropdown-toggle { + background-color: #e7649d!important +} + +.pink-skin .btn-secondary.dropdown-toggle:focus, +.pink-skin .btn-secondary.dropdown-toggle:hover { + background-color: #ea7aab!important +} + +.pink-skin .btn-default { + background-color: #535466 +} + +.pink-skin .btn-default:hover { + background-color: #5e6074!important +} + +.pink-skin .btn-default.active, +.pink-skin .btn-default:active, +.pink-skin .btn-default:focus { + background-color: #31313c!important +} + +.pink-skin .btn-default.dropdown-toggle { + background-color: #535466!important +} + +.pink-skin .btn-default.dropdown-toggle:focus, +.pink-skin .btn-default.dropdown-toggle:hover { + background-color: #5e6074!important +} + +.pink-skin .card .btn-action { + background: #535466 +} + +.pink-skin .card .btn-action:focus, +.pink-skin .card .btn-action:hover { + background-color: #5e6074!important +} + +.pink-skin .card .btn-action.active { + background-color: #25262e!important +} + +.pink-skin input[type=email]:focus:not([readonly]), +.pink-skin input[type=text]:focus:not([readonly]), +.pink-skin input[type=password]:focus:not([readonly]), +.pink-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #9fa0ae; + -webkit-box-shadow: 0 1px 0 0 #9fa0ae; + box-shadow: 0 1px 0 0 #9fa0ae +} + +.pink-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #9fa0ae; + border-bottom: 2px solid #9fa0ae +} + +.pink-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.pink-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #9fa0ae; + border-color: #9fa0ae +} + +.pink-skin .top-nav-collapse { + background-color: #535466 +} + +.pink-skin .carousel-multi-item .carousel-indicators li, +.pink-skin .carousel-multi-item .carousel-indicators li.active, +.pink-skin .carousel-multi-item .controls-top>a { + background-color: #9fa0ae +} + +.pink-skin .card-header, +.pink-skin .form-header { + background-color: #a5a5b3 +} + +.pink-skin .spinner-primary-color, +.pink-skin .spinner-primary-color-only { + border-color: #bd5d70 +} + +.pink-skin .pagination-primary-color .page-item.active .page-link, +.pink-skin .pagination-primary-color .page-item.active .page-link:focus, +.pink-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #bd5d70; + border-color: #bd5d70 +} + +.pink-skin .pagination-primary-color .page-link { + color: #bd5d70 +} + +.indigo-skin .gradient { + background: #272d6e; + background: -webkit-linear-gradient(315deg, #272d6e 0, #90a8ff 100%); + background: linear-gradient(135deg, #272d6e 0, #90a8ff 100%) +} + +.indigo-skin .primary-color, +.indigo-skin .stepper li.active a .circle, +.indigo-skin .stepper li.completed a .circle, +.stepper li.active a .indigo-skin .circle, +.stepper li.completed a .indigo-skin .circle { + background-color: #7f82c5!important +} + +.indigo-skin .navbar { + background-color: #9095aa; + color: #fff +} + +.indigo-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.indigo-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.indigo-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #fd4d79 +} + +.indigo-skin .page-footer { + background-color: #9095aa +} + +.indigo-skin .side-nav { + background-color: #404f9f +} + +.indigo-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.indigo-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #fc1a53 +} + +.indigo-skin .side-nav .social a:hover .fa { + color: #fd668c!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.indigo-skin .side-nav .collapsible li { + background-color: transparent +} + +.indigo-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.indigo-skin .side-nav .collapsible li .collapsible-header.active, +.indigo-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(250, 80, 121, .8) +} + +.indigo-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.indigo-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #ff89ac +} + +.indigo-skin .side-nav .fa { + color: #fff +} + +.indigo-skin .dropdown-content li:not(.disabled) span, +.indigo-skin .md-form .prefix.active, +.indigo-skin input[type=email]:focus:not([readonly])+label, +.indigo-skin input[type=text]:focus:not([readonly])+label, +.indigo-skin input[type=password]:focus:not([readonly])+label, +.indigo-skin textarea.md-textarea:focus:not([readonly])+label { + color: #fd668c +} + +.indigo-skin .side-nav .sidenav-bg.mask-strong:after, +.indigo-skin .side-nav .sidenav-bg:after { + background: rgba(35, 65, 134, .8) +} + +.indigo-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(35, 65, 134, .65) +} + +.indigo-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(35, 65, 134, .5) +} + +.indigo-skin .btn-primary { + background-color: #fd668c +} + +.indigo-skin .btn-primary:hover { + background-color: #fd7f9f!important +} + +.indigo-skin .btn-primary.active, +.indigo-skin .btn-primary:active, +.indigo-skin .btn-primary:focus { + background-color: #fc1a53!important +} + +.indigo-skin .btn-primary.dropdown-toggle { + background-color: #fd668c!important +} + +.indigo-skin .btn-primary.dropdown-toggle:focus, +.indigo-skin .btn-primary.dropdown-toggle:hover { + background-color: #fd7f9f!important +} + +.indigo-skin .btn-secondary { + background-color: #3c61ae +} + +.indigo-skin .btn-secondary:hover { + background-color: #456cbf!important +} + +.indigo-skin .btn-secondary.active, +.indigo-skin .btn-secondary:active, +.indigo-skin .btn-secondary:focus { + background-color: #284175!important +} + +.indigo-skin .btn-secondary.dropdown-toggle { + background-color: #3c61ae!important +} + +.indigo-skin .btn-secondary.dropdown-toggle:focus, +.indigo-skin .btn-secondary.dropdown-toggle:hover { + background-color: #456cbf!important +} + +.indigo-skin .btn-default { + background-color: #9095aa +} + +.indigo-skin .btn-default:hover { + background-color: #9ea3b5!important +} + +.indigo-skin .btn-default.active, +.indigo-skin .btn-default:active, +.indigo-skin .btn-default:focus { + background-color: #676d87!important +} + +.indigo-skin .btn-default.dropdown-toggle { + background-color: #9095aa!important +} + +.indigo-skin .btn-default.dropdown-toggle:focus, +.indigo-skin .btn-default.dropdown-toggle:hover { + background-color: #9ea3b5!important +} + +.indigo-skin .card .btn-action { + background: #9095aa +} + +.indigo-skin .card .btn-action:focus, +.indigo-skin .card .btn-action:hover { + background-color: #9ea3b5!important +} + +.indigo-skin .card .btn-action.active { + background-color: #5c6178!important +} + +.indigo-skin input[type=email]:focus:not([readonly]), +.indigo-skin input[type=text]:focus:not([readonly]), +.indigo-skin input[type=password]:focus:not([readonly]), +.indigo-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #fd668c; + -webkit-box-shadow: 0 1px 0 0 #fd668c; + box-shadow: 0 1px 0 0 #fd668c +} + +.indigo-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #fd668c; + border-bottom: 2px solid #fd668c +} + +.indigo-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.indigo-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #fd668c; + border-color: #fd668c +} + +.indigo-skin .top-nav-collapse { + background-color: #9095aa +} + +.indigo-skin .carousel-multi-item .carousel-indicators li, +.indigo-skin .carousel-multi-item .carousel-indicators li.active, +.indigo-skin .carousel-multi-item .controls-top>a { + background-color: #fd668c +} + +.indigo-skin .card-header, +.indigo-skin .form-header { + background-color: #fd7094 +} + +.indigo-skin .spinner-primary-color, +.indigo-skin .spinner-primary-color-only { + border-color: #7f82c5 +} + +.indigo-skin .pagination-primary-color .page-item.active .page-link, +.indigo-skin .pagination-primary-color .page-item.active .page-link:focus, +.indigo-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #7f82c5; + border-color: #7f82c5 +} + +.indigo-skin .pagination-primary-color .page-link { + color: #7f82c5 +} + +.light-blue-skin .gradient { + background: #69adf4; + background: -webkit-linear-gradient(315deg, #69adf4 0, #69adf4 100%); + background: linear-gradient(135deg, #69adf4 0, #69adf4 100%) +} + +.light-blue-skin .primary-color, +.light-blue-skin .stepper li.active a .circle, +.light-blue-skin .stepper li.completed a .circle, +.stepper li.active a .light-blue-skin .circle, +.stepper li.completed a .light-blue-skin .circle { + background-color: #3d799c!important +} + +.light-blue-skin .navbar { + background-color: #3f5c80; + color: #fff +} + +.light-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.light-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.light-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #a5b6be +} + +.light-blue-skin .page-footer { + background-color: #3f5c80 +} + +.light-blue-skin .side-nav { + background-color: #6a9ed3 +} + +.light-blue-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.light-blue-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #889ea9 +} + +.light-blue-skin .side-nav .social a:hover .fa { + color: #b4c2c9!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.light-blue-skin .side-nav .collapsible li { + background-color: transparent +} + +.light-blue-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.light-blue-skin .side-nav .collapsible li .collapsible-header.active, +.light-blue-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(29, 54, 86, .6) +} + +.light-blue-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.light-blue-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #aadeff +} + +.light-blue-skin .side-nav .fa { + color: #fff +} + +.light-blue-skin .dropdown-content li:not(.disabled) span, +.light-blue-skin .md-form .prefix.active, +.light-blue-skin input[type=email]:focus:not([readonly])+label, +.light-blue-skin input[type=text]:focus:not([readonly])+label, +.light-blue-skin input[type=password]:focus:not([readonly])+label, +.light-blue-skin textarea.md-textarea:focus:not([readonly])+label { + color: #b4c2c9 +} + +.light-blue-skin .side-nav .sidenav-bg.mask-strong:after, +.light-blue-skin .side-nav .sidenav-bg:after { + background: rgba(87, 134, 180, .8) +} + +.light-blue-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(87, 134, 180, .65) +} + +.light-blue-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(87, 134, 180, .5) +} + +.light-blue-skin .btn-primary { + background-color: #ff4a67 +} + +.light-blue-skin .btn-primary:hover { + background-color: #ff647c!important +} + +.light-blue-skin .btn-primary.active, +.light-blue-skin .btn-primary:active, +.light-blue-skin .btn-primary:focus { + background-color: #fd0028!important +} + +.light-blue-skin .btn-primary.dropdown-toggle { + background-color: #ff4a67!important +} + +.light-blue-skin .btn-primary.dropdown-toggle:focus, +.light-blue-skin .btn-primary.dropdown-toggle:hover { + background-color: #ff647c!important +} + +.light-blue-skin .btn-secondary { + background-color: #64c3f0 +} + +.light-blue-skin .btn-secondary:hover { + background-color: #7bccf2!important +} + +.light-blue-skin .btn-secondary.active, +.light-blue-skin .btn-secondary:active, +.light-blue-skin .btn-secondary:focus { + background-color: #1ea8e9!important +} + +.light-blue-skin .btn-secondary.dropdown-toggle { + background-color: #64c3f0!important +} + +.light-blue-skin .btn-secondary.dropdown-toggle:focus, +.light-blue-skin .btn-secondary.dropdown-toggle:hover { + background-color: #7bccf2!important +} + +.light-blue-skin .btn-default { + background-color: #2d486a +} + +.light-blue-skin .btn-default:hover { + background-color: #35547c!important +} + +.light-blue-skin .btn-default.active, +.light-blue-skin .btn-default:active, +.light-blue-skin .btn-default:focus { + background-color: #162434!important +} + +.light-blue-skin .btn-default.dropdown-toggle { + background-color: #2d486a!important +} + +.light-blue-skin .btn-default.dropdown-toggle:focus, +.light-blue-skin .btn-default.dropdown-toggle:hover { + background-color: #35547c!important +} + +.light-blue-skin .card .btn-action { + background: #2d486a +} + +.light-blue-skin .card .btn-action:focus, +.light-blue-skin .card .btn-action:hover { + background-color: #35547c!important +} + +.light-blue-skin .card .btn-action.active { + background-color: #0f1722!important +} + +.light-blue-skin input[type=email]:focus:not([readonly]), +.light-blue-skin input[type=text]:focus:not([readonly]), +.light-blue-skin input[type=password]:focus:not([readonly]), +.light-blue-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #b4c2c9; + -webkit-box-shadow: 0 1px 0 0 #b4c2c9; + box-shadow: 0 1px 0 0 #b4c2c9 +} + +.light-blue-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #b4c2c9; + border-bottom: 2px solid #b4c2c9 +} + +.light-blue-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.light-blue-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #b4c2c9; + border-color: #b4c2c9 +} + +.light-blue-skin .top-nav-collapse { + background-color: #3f5c80 +} + +.light-blue-skin .carousel-multi-item .carousel-indicators li, +.light-blue-skin .carousel-multi-item .carousel-indicators li.active, +.light-blue-skin .carousel-multi-item .controls-top>a { + background-color: #b4c2c9 +} + +.light-blue-skin .card-header, +.light-blue-skin .form-header { + background-color: #bac7cd +} + +.light-blue-skin .spinner-primary-color, +.light-blue-skin .spinner-primary-color-only { + border-color: #3d799c +} + +.light-blue-skin .pagination-primary-color .page-item.active .page-link, +.light-blue-skin .pagination-primary-color .page-item.active .page-link:focus, +.light-blue-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #3d799c; + border-color: #3d799c +} + +.light-blue-skin .pagination-primary-color .page-link { + color: #3d799c +} + +.grey-skin .gradient { + background: #383838; + background: -webkit-linear-gradient(315deg, #383838 0, #a5a4a4 100%); + background: linear-gradient(135deg, #383838 0, #a5a4a4 100%) +} + +.grey-skin .primary-color, +.grey-skin .stepper li.active a .circle, +.grey-skin .stepper li.completed a .circle, +.stepper li.active a .grey-skin .circle, +.stepper li.completed a .grey-skin .circle { + background-color: #2b2b2b!important +} + +.grey-skin .navbar { + background-color: #44474b; + color: #fff +} + +.grey-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.grey-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.grey-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #5eb7ee +} + +.grey-skin .page-footer { + background-color: #44474b +} + +.grey-skin .side-nav { + background-color: #a5a4a4 +} + +.grey-skin .side-nav .logo-wrapper>div { + background-color: transparent!important +} + +.grey-skin .side-nav .sn-avatar-wrapper img { + border: 3px solid #30a2e9 +} + +.grey-skin .side-nav .social a:hover .fa { + color: #75c1f0!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.grey-skin .side-nav .collapsible li { + background-color: transparent +} + +.grey-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.grey-skin .side-nav .collapsible li .collapsible-header.active, +.grey-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(0, 0, 0, .4) +} + +.grey-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.grey-skin .side-nav .collapsible li .collapsible-body a:hover { + color: #afdffc +} + +.grey-skin .side-nav .fa { + color: #fff +} + +.grey-skin .dropdown-content li:not(.disabled) span, +.grey-skin .md-form .prefix.active, +.grey-skin input[type=email]:focus:not([readonly])+label, +.grey-skin input[type=text]:focus:not([readonly])+label, +.grey-skin input[type=password]:focus:not([readonly])+label, +.grey-skin textarea.md-textarea:focus:not([readonly])+label { + color: #75c1f0 +} + +.grey-skin .side-nav .sidenav-bg.mask-strong:after, +.grey-skin .side-nav .sidenav-bg:after { + background: rgba(121, 121, 121, .8) +} + +.grey-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(121, 121, 121, .65) +} + +.grey-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(121, 121, 121, .5) +} + +.grey-skin .btn-primary { + background-color: #46aded +} + +.grey-skin .btn-primary:hover { + background-color: #5db7ef!important +} + +.grey-skin .btn-primary.active, +.grey-skin .btn-primary:active, +.grey-skin .btn-primary:focus { + background-color: #1489d2!important +} + +.grey-skin .btn-primary.dropdown-toggle { + background-color: #46aded!important +} + +.grey-skin .btn-primary.dropdown-toggle:focus, +.grey-skin .btn-primary.dropdown-toggle:hover { + background-color: #5db7ef!important +} + +.grey-skin .btn-secondary { + background-color: #7d8488 +} + +.grey-skin .btn-secondary:hover { + background-color: #8a9194!important +} + +.grey-skin .btn-secondary.active, +.grey-skin .btn-secondary:active, +.grey-skin .btn-secondary:focus { + background-color: #585d60!important +} + +.grey-skin .btn-secondary.dropdown-toggle { + background-color: #7d8488!important +} + +.grey-skin .btn-secondary.dropdown-toggle:focus, +.grey-skin .btn-secondary.dropdown-toggle:hover { + background-color: #8a9194!important +} + +.grey-skin .btn-default { + background-color: #353637 +} + +.grey-skin .btn-default:hover { + background-color: #424344!important +} + +.grey-skin .btn-default.active, +.grey-skin .btn-default:active, +.grey-skin .btn-default:focus { + background-color: #0f1010!important +} + +.grey-skin .btn-default.dropdown-toggle { + background-color: #353637!important +} + +.grey-skin .btn-default.dropdown-toggle:focus, +.grey-skin .btn-default.dropdown-toggle:hover { + background-color: #424344!important +} + +.grey-skin .card .btn-action { + background: #353637 +} + +.grey-skin .card .btn-action:focus, +.grey-skin .card .btn-action:hover { + background-color: #424344!important +} + +.grey-skin .card .btn-action.active { + background-color: #030303!important +} + +.grey-skin input[type=email]:focus:not([readonly]), +.grey-skin input[type=text]:focus:not([readonly]), +.grey-skin input[type=password]:focus:not([readonly]), +.grey-skin textarea.md-textarea:focus:not([readonly]) { + border-color: #75c1f0; + -webkit-box-shadow: 0 1px 0 0 #75c1f0; + box-shadow: 0 1px 0 0 #75c1f0 +} + +.grey-skin input[type=checkbox]:checked+label:before { + border-right: 2px solid #75c1f0; + border-bottom: 2px solid #75c1f0 +} + +.grey-skin input[type=checkbox].filled-in:checked+label:before { + border-right: 2px solid #fff; + border-bottom: 2px solid #fff +} + +.grey-skin input[type=checkbox].filled-in:checked+label:after { + background-color: #75c1f0; + border-color: #75c1f0 +} + +.grey-skin .top-nav-collapse { + background-color: #44474b +} + +.grey-skin .carousel-multi-item .carousel-indicators li, +.grey-skin .carousel-multi-item .carousel-indicators li.active, +.grey-skin .carousel-multi-item .controls-top>a { + background-color: #75c1f0 +} + +.grey-skin .card-header, +.grey-skin .form-header { + background-color: #7ec5f1 +} + +.grey-skin .spinner-primary-color, +.grey-skin .spinner-primary-color-only { + border-color: #2b2b2b +} + +.grey-skin .pagination-primary-color .page-item.active .page-link, +.grey-skin .pagination-primary-color .page-item.active .page-link:focus, +.grey-skin .pagination-primary-color .page-item.active .page-link:hover { + color: #fff; + background-color: #2b2b2b; + border-color: #2b2b2b +} + +.grey-skin .pagination-primary-color .page-link { + color: #2b2b2b +} + +.picker__input { + cursor: default +} + +.picker { + font-size: 16px; + text-align: center; + line-height: 1.2; + color: #000; + position: absolute; + z-index: 10000; + user-select: none +} + +.picker .picker__holder { + width: 100%; + overflow-y: auto; + overflow-scrolling: touch; + position: fixed; + -webkit-transition: background .15s ease-out, top 0s .15s; + transition: background .15s ease-out, top 0s .15s; + -webkit-backface-visibility: hidden; + backface-visibility: hidden +} + +.picker .picker__frame, +.picker .picker__holder { + bottom: 0; + left: 0; + right: 0; + top: 100% +} + +.picker .picker__frame { + position: absolute; + margin: 0 auto; + min-width: 256px; + max-width: 325px; + width: 300px; + max-height: 350px; + filter: alpha(opacity=0); + opacity: 0; + -webkit-transition: all .15s ease-out; + transition: all .15s ease-out +} + +@media (min-height: 40.125em) { + .picker .picker__frame { + margin-bottom: 7.5% + } +} + +.picker .picker__frame .picker__wrap { + display: table; + width: 100%; + height: 100% +} + +@media (min-height: 28.875em) { + .picker .picker__frame { + overflow: visible; + top: auto; + bottom: -100%; + max-height: 80% + } + .picker .picker__frame .picker__wrap { + display: block + } +} + +.picker .picker__box { + background: #fff; + display: table-cell +} + +@media (min-height: 28.875em) { + .picker .picker__box { + display: block; + border: 1px solid #777; + border-top-color: #898989; + border-bottom-width: 0; + border-radius: 5px 5px 0 0; + -webkit-box-shadow: 0 12px 36px 16px rgba(0, 0, 0, .24); + box-shadow: 0 12px 36px 16px rgba(0, 0, 0, .24) + } +} + +.picker--opened .picker__holder { + top: 0; + zoom: 1; + background: rgba(0, 0, 0, .32); + -webkit-transition: background .15s ease-out; + transition: background .15s ease-out +} + +.picker--opened .picker__frame { + top: 0; + filter: alpha(opacity=100); + opacity: 1 +} + +@media (min-height: 35.875em) { + .picker--opened .picker__frame { + top: 10%; + bottom: auto + } +} + +.picker__input.picker__input--active { + border-color: #E3F2FD +} + +.picker__list { + list-style: none; + padding: .75em 0 4.2em; + margin: 0 +} + +.picker__list-item { + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + margin-bottom: -1px; + position: relative; + padding: .75em 1.25em +} + +.picker__list-item--highlighted, +.picker__list-item:hover { + border-color: #0089ec; + z-index: 10 +} + +@media (min-height: 46.75em) { + .picker__list-item { + padding: .5em 1em + } +} + +.picker__list-item:hover { + cursor: pointer; + background: #b1dcfb +} + +.picker--focused .picker__list-item--highlighted, +.picker__list-item--highlighted:hover { + cursor: pointer; + color: #000; + background: #b1dcfb +} + +.picker--focused .picker__list-item--selected, +.picker__list-item--selected, +.picker__list-item--selected:hover { + background: #0089ec; + z-index: 10 +} + +.picker--focused .picker__list-item--disabled, +.picker__list-item--disabled, +.picker__list-item--disabled:hover { + background: #f5f5f5; + color: #ddd; + cursor: default; + border-color: #ddd; + z-index: auto +} + +.picker--time .picker__button--clear { + display: block; + width: 80%; + margin: 1em auto 0; + padding: 1em 1.25em; + background: 0 0; + border: 0; + font-weight: 500; + font-size: .67em; + text-align: center; + text-transform: uppercase; + color: #666 +} + +.picker--time .picker__button--clear:focus, +.picker--time .picker__button--clear:hover { + color: #000; + background: #e20; + border-color: #e20; + cursor: pointer; + outline: 0 +} + +.picker--time .picker__button--clear:before { + top: -.25em; + color: #666; + font-size: 1.25em; + font-weight: 700 +} + +.picker--time .picker__frame { + min-width: 256px; + max-width: 320px +} + +.picker--time .picker__box { + font-size: 1em; + background: #f2f2f2; + padding: 0 +} + +@media (min-height: 40.125em) { + .picker--time .picker__box { + margin-bottom: 5em + } +} + +.picker__date-display { + text-align: center; + background-color: #4285F4; + padding-bottom: 15px; + font-weight: 300; + margin-bottom: 1rem +} + +.picker__date-display .clockpicker-display { + display: inline-block; + margin: auto; + height: 85px; + font-size: 70px; + padding: 10px 10px 0; + color: #b2dfdb +} + +.picker__date-display .clockpicker-display .clockpicker-display-column #click-am.text-primary, +.picker__date-display .clockpicker-display .clockpicker-display-column #click-pm.text-primary, +.picker__date-display .clockpicker-display .clockpicker-display-column .clockpicker-span-hours.text-primary, +.picker__date-display .clockpicker-display .clockpicker-display-column .clockpicker-span-minutes.text-primary { + -webkit-animation-name: pulse; + animation-name: pulse +} + +.picker__date-display .clockpicker-display .clockpicker-display-column #click-am, +.picker__date-display .clockpicker-display .clockpicker-display-column #click-pm { + cursor: pointer +} + +.picker__date-display .clockpicker-display .clockpicker-display-am-pm { + padding-left: 5px; + vertical-align: bottom; + height: 85px +} + +.picker__date-display .clockpicker-display .clockpicker-display-am-pm .clockpicker-span-am-pm { + display: inline-block; + font-size: 23px; + line-height: 25px; + color: #b2dfdb +} + +.picker__date-display .clockpicker-display .clockpicker-span-hours, +.picker__date-display .clockpicker-display .clockpicker-span-minutes { + -webkit-animation-duration: .5s; + animation-duration: .5s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-transition: color .5s; + transition: color .5s; + cursor: pointer +} + +.clockpicker-display { + text-align: center; + vertical-align: middle; + display: inline-block; + margin: auto; + height: 85px; + font-size: 70px; + padding: 10px 10px 0; + color: #b2dfdb +} + +.clockpicker-display .clockpicker-display-column #click-am.text-primary, +.clockpicker-display .clockpicker-display-column #click-pm.text-primary, +.clockpicker-display .clockpicker-display-column .clockpicker-span-hours.text-primary, +.clockpicker-display .clockpicker-display-column .clockpicker-span-minutes.text-primary { + -webkit-animation-name: pulse; + animation-name: pulse +} + +.clockpicker-display .clockpicker-display-column #click-am, +.clockpicker-display .clockpicker-display-column #click-pm { + cursor: pointer +} + +.clockpicker-display .clockpicker-display-am-pm { + padding-left: 5px; + vertical-align: bottom; + height: 85px +} + +.clockpicker-display .clockpicker-display-am-pm .clockpicker-span-am-pm { + display: inline-block; + font-size: 23px; + line-height: 25px; + color: #b2dfdb +} + +.clockpicker-display .clockpicker-span-hours, +.clockpicker-display .clockpicker-span-minutes { + -webkit-animation-duration: .5s; + animation-duration: .5s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-transition: color .5s; + transition: color .5s; + cursor: pointer +} + +@keyframes pulse { + from, + to { + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1) + } + 50% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1) + } +} + +.clockpicker-moving { + cursor: move +} + +.clockpicker-plate { + background-color: #eee; + border-radius: 50%; + width: 270px; + height: 270px; + overflow: visible; + position: relative; + margin: 20px auto auto; + user-select: none +} + +.clockpicker-plate .clockpicker-canvas, +.clockpicker-plate .clockpicker-dial { + width: 270px; + height: 270px; + position: absolute; + left: -1px; + top: -1px +} + +.clockpicker-plate .clockpicker-dial { + -webkit-transition: opacity 350ms, -webkit-transform 350ms; + transition: opacity 350ms, -webkit-transform 350ms; + transition: transform 350ms, opacity 350ms; + transition: transform 350ms, opacity 350ms, -webkit-transform 350ms +} + +.clockpicker-plate .clockpicker-dial .clockpicker-tick { + border-radius: 50%; + color: #666; + line-height: 40px; + text-align: center; + width: 40px; + height: 40px; + position: absolute; + cursor: pointer; + -webkit-transition: background-color .3s; + transition: background-color .3s; + background-color: rgba(0, 150, 136, 0) +} + +.clockpicker-plate .clockpicker-dial .clockpicker-tick.active, +.clockpicker-plate .clockpicker-dial .clockpicker-tick:hover { + background-color: rgba(0, 150, 136, .25) +} + +.clockpicker-plate .clockpicker-minutes { + visibility: hidden +} + +.clockpicker-plate .clockpicker-dial-out { + opacity: 0 +} + +.clockpicker-plate .clockpicker-hours.clockpicker-dial-out { + -webkit-transform: scale(1.2, 1.2); + -ms-transform: scale(1.2, 1.2); + transform: scale(1.2, 1.2) +} + +.clockpicker-plate .clockpicker-minutes.clockpicker-dial-out { + -webkit-transform: scale(.8, .8); + -ms-transform: scale(.8, .8); + transform: scale(.8, .8) +} + +.clockpicker-canvas { + -webkit-transition: opacity .3s; + transition: opacity .3s +} + +.clockpicker-canvas line { + stroke: rgba(0, 150, 136, .25); + stroke-width: 1 +} + +.clockpicker-canvas-out { + opacity: .25 +} + +.clockpicker-canvas-bearing { + stroke: none; + fill: rgba(0, 77, 64, .75) +} + +.clockpicker-canvas-fg { + stroke: none; + fill: rgba(0, 77, 64, 0) +} + +.clockpicker-canvas-fg.active { + fill: rgba(0, 77, 64, .5) +} + +.clockpicker-canvas-bg, +.clockpicker-canvas-bg-trans { + fill: rgba(0, 150, 136, .25) +} + +.clockpicker-canvas-bg { + stroke: none +} + +.clockpicker-am-pm-block { + margin-top: -10px; + width: 100%; + height: 50px +} + +.clockpicker-am-pm-block .clockpicker-button.am-button { + height: 45px; + width: 45px; + float: left +} + +.clockpicker-am-pm-block .clockpicker-button.pm-button { + height: 45px; + width: 45px; + float: right +} + +.btn-floating.btn-flat { + padding: 0; + background: #4285F4 +} + +.btn-floating.btn-flat:hover { + -webkit-box-shadow: none; + box-shadow: none +} + +.btn-floating.btn-flat:focus, +.btn-floating.btn-flat:hover { + background-color: #5a95f5!important +} + +.btn-floating.btn-flat.active { + background-color: #0b51c5!important +} + +.picker__footer .clockpicker-button { + margin: 15px auto auto; + background-color: transparent; + text-transform: uppercase +} + +.picker__footer .clockpicker-button:focus { + background-color: transparent +} + +.picker__footer .clockpicker-button:active { + background-color: rgba(0, 150, 136, .25) +} + +.darktheme .picker__box { + background-color: #212121 +} + +.darktheme .picker__box .picker__calendar-container .clockpicker-plate, +.darktheme .picker__box .picker__date-display { + background-color: transparent +} + +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-tick { + background-color: rgba(255, 64, 129, 0) +} + +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-tick.active, +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-tick:hover, +.darktheme .picker__box .picker__footer .clockpicker-button:active { + background-color: rgba(255, 64, 129, .25) +} + +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas line { + stroke: rgba(255, 64, 129, .25) +} + +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-bearing { + fill: #fff +} + +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-fg { + fill: rgba(255, 64, 129, 0) +} + +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-fg.active { + fill: rgba(255, 64, 129, .5) +} + +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-bg, +.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-bg-trans { + fill: rgba(255, 64, 129, .25) +} + +.picker__box { + padding: 0; + border-radius: 2px; + overflow: hidden +} + +.picker__box .picker__header { + text-align: center; + position: relative; + margin-bottom: 20px +} + +.picker__box .picker__header select { + display: inline-block!important +} + +.picker__box .picker__header .picker__date-display { + text-align: center; + background-color: #4285F4; + padding-bottom: 15px; + font-weight: 300; + margin-bottom: 1rem +} + +.picker__box .picker__header .picker__date-display .picker__weekday-display { + background-color: #206ff2; + padding: 10px; + font-weight: 200; + letter-spacing: .5; + font-size: 1rem; + margin-bottom: 15px +} + +.picker__box .picker__header .picker__date-display .picker__month-display { + text-transform: uppercase; + font-size: 2rem +} + +.picker__box .picker__header .picker__date-display .picker__day-display { + font-size: 4.5rem; + font-weight: 400 +} + +.picker__box .picker__header .picker__date-display .picker__year-display { + font-size: 1.8rem; + color: rgba(255, 255, 255, .4) +} + +.picker__box .picker__header .picker__month, +.picker__box .picker__header .picker__year { + display: inline-block; + margin-left: .25em; + margin-right: .25em +} + +.picker__box .picker__header .picker__select--month, +.picker__box .picker__header .picker__select--year { + height: 2em; + padding: 0; + margin-left: .25em; + margin-right: .25em; + display: inline-block +} + +.picker__box .picker__header .picker__select--month:focus, +.picker__box .picker__header .picker__select--year:focus { + border-color: rgba(0, 0, 0, .05) +} + +.picker__box .picker__header .picker__select--year { + width: 30% +} + +.picker__box .picker__header .picker__select--month.browser-default { + display: inline; + width: 40% +} + +.picker__box .picker__header .picker__select--year.browser-default { + display: inline; + width: 25% +} + +.picker__box .picker__header .picker__nav--next, +.picker__box .picker__header .picker__nav--prev { + position: absolute; + padding: .5em 1.55em; + width: 1em; + height: 1em; + -webkit-box-sizing: content-box; + box-sizing: content-box; + bottom: 0 +} + +.picker__box .picker__header .picker__nav--next:hover, +.picker__box .picker__header .picker__nav--prev:hover { + cursor: pointer; + color: #000; + background: #ecf2fc +} + +.picker__box .picker__header .picker__nav--next:before, +.picker__box .picker__header .picker__nav--prev:before { + content: " "; + border-top: .5em solid transparent; + border-bottom: .5em solid transparent; + border-right: .75em solid #676767; + width: 0; + height: 0; + display: block; + margin: 0 auto +} + +.picker__box .picker__header .picker__nav--prev { + left: -1em; + padding-right: 1.25em +} + +.picker__box .picker__header .picker__nav--next { + right: -1em; + padding-left: 1.25em +} + +.picker__box .picker__header .picker__nav--next:before { + border-right: 0; + border-left: .75em solid #676767 +} + +.picker__box .picker__header .picker__nav--disabled, +.picker__box .picker__header .picker__nav--disabled:before, +.picker__box .picker__header .picker__nav--disabled:before:hover, +.picker__box .picker__header .picker__nav--disabled:hover { + cursor: default; + background: 0 0; + border-right-color: #f5f5f5; + border-left-color: #f5f5f5 +} + +.picker__box .picker__table { + text-align: center; + border-collapse: collapse; + border-spacing: 0; + table-layout: fixed; + font-size: 1rem; + width: 100%; + margin-top: .75em; + margin-bottom: .5em +} + +.picker__box .picker__table td, +.picker__box .picker__table th { + text-align: center +} + +.picker__box .picker__table td { + margin: 0; + padding: 0 +} + +.picker__box .picker__table .picker__weekday { + width: 14%; + font-size: .9em; + padding-bottom: .25em; + color: #999; + font-weight: 500 +} + +@media (min-height: 33.875em) { + .picker__box .picker__table .picker__weekday { + padding-bottom: .5em + } +} + +.picker__box .picker__table .picker__day--today { + position: relative; + letter-spacing: -.3; + padding: .75rem 0; + font-weight: 400; + border: 1px solid transparent +} + +.picker__box .picker__table .picker__day.picker__day--today { + color: #4285F4 +} + +.picker__box .picker__table .picker__day--disabled:before { + border-top-color: #aaa +} + +.picker__box .picker__table .picker__day--infocus { + color: #595959; + letter-spacing: -.3; + padding: .75rem 0; + font-weight: 400; + border: 1px solid transparent +} + +.picker__box .picker__table .picker__day--infocus:hover { + cursor: pointer; + color: #000; + font-weight: 500 +} + +.picker__box .picker__table .picker__day--outfocus { + display: none; + padding: .75rem 0 +} + +.picker__box .picker__table .picker__day--outfocus:hover { + cursor: pointer; + color: #ddd; + font-weight: 500 +} + +.picker__box .picker__table .picker--focused .picker__day--highlighted, +.picker__box .picker__table .picker__day--highlighted:hover { + cursor: pointer +} + +.picker__box .picker__table .picker--focused, +.picker__box .picker__table .picker__day--selected, +.picker__box .picker__table .picker__day--selected:hover { + border-radius: 50%; + -webkit-transform: scale(.9); + -ms-transform: scale(.9); + transform: scale(.9); + background-color: #4285F4 +} + +.picker__box .picker__table .picker--focused.picker__day--outfocus, +.picker__box .picker__table .picker__day--selected.picker__day--outfocus, +.picker__box .picker__table .picker__day--selected:hover.picker__day--outfocus { + background-color: #ecf2fc +} + +.picker__box .picker__table .picker--focused, +.picker__box .picker__table .picker__day--disabled, +.picker__box .picker__table .picker__day--disabled:hover { + background: #f5f5f5; + border-color: #f5f5f5; + color: #ddd; + cursor: default +} + +.picker__box .picker__table .picker__day--highlighted.picker__day--disabled, +.picker__box .picker__table .picker__day--highlighted.picker__day--disabled:hover { + background: #bbb +} + +.picker__box .picker__footer { + text-align: right; + padding: 5px 10px; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between +} + +.picker__box .picker__footer .picker__button--clear, +.picker__box .picker__footer .picker__button--close, +.picker__box .picker__footer .picker__button--today { + border: 1px solid #fff; + background: #fff; + font-size: .8em; + padding: 1rem 0 .7rem; + font-weight: 700; + width: 33%; + display: inline-block; + vertical-align: bottom; + text-transform: uppercase +} + +.picker__box .picker__footer .picker__button--clear:hover, +.picker__box .picker__footer .picker__button--close:hover, +.picker__box .picker__footer .picker__button--today:hover { + cursor: pointer; + color: #000; + background: #b1dcfb; + border-bottom-color: #b1dcfb +} + +.picker__box .picker__footer .picker__button--clear:focus, +.picker__box .picker__footer .picker__button--close:focus, +.picker__box .picker__footer .picker__button--today:focus { + background: #b1dcfb; + border-color: rgba(0, 0, 0, .05); + outline: 0 +} + +.picker__box .picker__footer .picker__button--clear:before, +.picker__box .picker__footer .picker__button--close:before, +.picker__box .picker__footer .picker__button--today:before { + position: relative; + display: inline-block; + height: 0 +} + +.picker__box .picker__footer .picker__button--clear:before, +.picker__box .picker__footer .picker__button--today:before { + content: " "; + margin-right: .45em +} + +.picker__box .picker__footer .picker__button--today:before { + top: -.05em; + width: 0; + border-top: .66em solid #0059bc; + border-left: .66em solid transparent +} + +.picker__box .picker__footer .picker__button--clear:before { + top: -.25em; + width: .66em; + border-top: 3px solid #e20 +} + +.picker__box .picker__footer .picker__button--close:before { + content: "\D7"; + top: -.1em; + vertical-align: top; + font-size: 1.1em; + margin-right: .35em; + color: #777 +} + +.picker__box .picker__footer .picker__button--today[disabled], +.picker__box .picker__footer .picker__button--today[disabled]:hover { + background: #f5f5f5; + border-color: #f5f5f5; + color: #ddd; + cursor: default +} + +.picker__box .picker__footer .picker__button--today[disabled]:before { + border-top-color: #aaa +} + +.picker__calendar-container { + padding: 0 1rem +} + +.fixed-sn main, +.hidden-sn main { + padding-top: 5.5rem +} + +.picker__calendar-container thead { + border: none +} + +.section img { + max-width: 100%; + height: auto +} + +.fixed-sn .double-nav, +.fixed-sn footer, +.fixed-sn main { + padding-left: 240px +} + +@media (max-width: 1440px) { + .fixed-sn .double-nav, + .fixed-sn footer, + .fixed-sn main { + padding-left: 0 + } +} + +@media (min-width: 600px) { + .fixed-sn .page-footer .container-fluid, + .fixed-sn main { + margin-left: 2%; + margin-right: 2% + } +} + +@media (min-width: 992px) { + .fixed-sn .page-footer .container-fluid, + .fixed-sn main { + margin-left: 5%; + margin-right: 5% + } +} + +@media (min-width: 1200px) { + .fixed-sn .page-footer .container-fluid, + .fixed-sn main { + margin-left: 6%; + margin-right: 6% + } +} + +.hidden-sn .button-collapse { + display: block; + position: relative; + font-size: 1.4rem; + margin-right: 10px; + margin-left: -6px; + padding-left: 0 +} + +.feature-box { + text-align: center +} + +.feature-box .feature-title { + font-weight: 500; + margin-bottom: 1rem +} + +.feature-box .features-big .feature-title { + margin-top: 1.5rem; + margin-bottom: 1.5rem +} + +.feature-box .features-big .fa { + font-size: 4rem +} + +.feature-box .features-small { + text-align: left +} + +.section-blog-fw .author-box, +.section-blog-fw .jumbotron, +.section-heading { + text-align: center +} + +.feature-box .features-small .fa { + font-size: 2rem +} + +.mdb-feed { + margin: 1rem 0 +} + +.mdb-feed .news { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex +} + +.mdb-feed .news .label { + display: block; + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + -ms-grid-row-align: stretch; + align-self: stretch; + width: 2.5rem +} + +.mdb-feed .news .label img { + width: 100%; + height: auto +} + +.mdb-feed .news .excerpt { + display: block; + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + -ms-grid-row-align: stretch; + align-self: stretch; + word-wrap: break-word; + margin: 0 0 1.2rem 1.2rem +} + +.mdb-feed .news .excerpt .brief { + padding-bottom: .5rem; + font-weight: 500 +} + +.mdb-feed .news .excerpt .brief a { + color: #4285F4 +} + +.mdb-feed .news .excerpt .brief .date, +.mdb-feed .news .excerpt .feed-footer .like { + font-weight: 300; + color: #9e9e9e; + font-size: .86rem +} + +.mdb-feed .news .excerpt .brief .name { + display: inline-block; + vertical-align: baseline +} + +.mdb-feed .news .excerpt .brief .date { + display: inline-block; + float: none; + padding-left: .7rem +} + +.mdb-feed .news .excerpt .added-images { + margin-bottom: .6rem +} + +.mdb-feed .news .excerpt .added-images img { + display: inline-block; + margin-right: .3rem; + width: 7rem +} + +.mdb-feed .news .excerpt .added-text { + margin-bottom: .6rem; + max-width: 450px +} + +.mdb-feed .news .excerpt .feed-footer .like:hover .fa { + color: #F44336; + -webkit-transition: .4s; + transition: .4s +} + +.mdb-feed .news .excerpt .feed-footer .like:hover span { + color: #000; + -webkit-transition: .4s; + transition: .4s +} + +.mdb-feed .news .excerpt .feed-footer .like .fa { + padding-right: .5rem +} + +.mdb-feed .news .excerpt .feed-footer span a { + padding-right: .3rem; + color: #4285F4; + cursor: default +} + +.mdb-feed .news .excerpt .feed-footer .thumbs .fa { + color: #9e9e9e; + -webkit-transition: .4s; + transition: .4s +} + +.mdb-feed .news .excerpt .feed-footer .thumbs .fa:hover { + color: #757575 +} + +.mdb-feed .news .excerpt .feed-footer .thumbs .fa-thumbs-up { + padding-right: .3rem +} + +.mdb-feed .news .excerpt .feed-footer .comment { + color: #9e9e9e +} + +.card-personal .card-body .card-title { + font-weight: 400; + margin-bottom: .3rem +} + +.card-personal .card-body .card-title.title-one { + -webkit-transition: .4s; + transition: .4s +} + +.card-personal .card-body .card-title.title-one:hover { + color: #4285F4 +} + +.card-personal .card-body .card-meta { + font-weight: 300; + font-size: .86rem; + color: #757575 +} + +.card-personal .card-body .card-meta .fa { + padding-right: .5rem +} + +.card-personal .card-body span { + -webkit-transition: .5s; + transition: .5s +} + +.card-personal .card-body span:hover { + color: #4285F4 +} + +.news-card .content .right-side-meta { + float: right; + font-weight: 300; + color: #9e9e9e; + margin-top: .3rem +} + +.news-card .content .avatar-img { + width: 2rem; + margin-right: 1rem +} + +.news-card .content img { + border-radius: 50%; + display: inline-block; + vertical-align: middle; + max-width: 100% +} + +.news-card .social-meta .fa { + padding-right: .6rem +} + +.news-card .social-meta .fa-heart-o { + cursor: pointer; + color: rgba(0, 0, 0, .4); + -webkit-transition: .53s; + transition: .53s +} + +.news-card .social-meta .fa-heart-o:hover { + color: #F44336 +} + +.news-card .social-meta span { + float: right +} + +.news-card .md-form { + margin-top: 1.3rem; + margin-bottom: .3rem +} + +.news-card .md-form .prefix { + font-size: 1.5rem; + margin-left: .2rem; + color: rgba(0, 0, 0, .4) +} + +.news-card .md-form .prefix .md-form .prefix~textarea, +.news-card .md-form .prefix~input { + width: -webkit-calc(100% - 4rem); + width: calc(100% - 4rem) +} + +.news-card .md-form .prefix.active { + color: rgba(0, 0, 0, .4) +} + +.news-card .md-form .form-control { + padding-top: 0; + padding-bottom: .5rem; + margin-left: 3rem; + margin-bottom: 0; + height: 1.3rem; + border-bottom: 1px solid rgba(0, 0, 0, .1) +} + +.no-radius { + border-radius: 0!important +} + +.section .section-heading { + margin-top: 2rem; + margin-bottom: 4rem +} + +.section-heading h1 { + margin-top: 2rem; + margin-bottom: 3rem +} + +.section-heading p { + margin-bottom: 3rem; + margin-right: 15%; + margin-left: 15% +} + +.section-description { + color: #757575; + margin-bottom: 4rem; + margin-left: 15%; + margin-right: 15%; + text-align: center +} + +@media (max-width: 992px) { + .section-description { + margin-left: 5%; + margin-right: 5% + } +} + +.section-blog-fw .view img { + border-radius: 2px +} + +.section-blog-fw h2 { + font-weight: 300 +} + +.section-blog-fw h2 a { + color: #424242; + -webkit-transition: .2s; + transition: .2s +} + +.section-blog-fw h2 a:hover { + color: #616161; + -webkit-transition: .2s; + transition: .2s +} + +.section-blog-fw .excerpt, +.section-blog-fw .post-text { + margin-left: 10%; + margin-right: 10%; + text-align: justify +} + +@media (max-width: 992px) { + .section-blog-fw .excerpt, + .section-blog-fw .post-text { + margin-left: 5%; + margin-right: 5% + } +} + +.section-blog-fw hr { + display: block +} + +@media (min-width: 1200px) { + .hr-width { + width: 83% + } +} + +.section.team-section .avatar { + margin-bottom: 2rem; + height: auto +} + +.section.team-section .avatar .rounded-circle { + max-width: 170px +} + +.section.team-section .avatar img { + max-width: 200px; + height: auto +} + +.section.team-section .title-color { + font-weight: 400; + color: rgba(0, 0, 0, .6) +} + +.section.team-section h4, +.section.team-section h5 { + margin-bottom: 1rem +} + +.section.team-section .grey-text { + color: #6e6e6e!important +} + +.section h4 { + font-weight: 400 +} + +.section .card-wrapper .fa-repeat, +.section .card-wrapper .fa-undo { + font-size: 15px +} + +.testimonial-carousel .carousel-control { + background-image: none; + top: 50%; + -webkit-transform: translateY(-35%); + -ms-transform: translateY(-35%); + transform: translateY(-35%) +} + +.testimonial-carousel .carousel-control:before { + font-size: 5rem; + color: rgba(0, 0, 0, .6) +} + +.testimonial-carousel .carousel-control:hover:before { + color: #000; + -webkit-transition: .4s; + transition: .4s +} + +.testimonial-carousel .carousel-control.left { + left: 6% +} + +.testimonial-carousel .carousel-control.left:before { + content: "\2039" +} + +.testimonial-carousel .carousel-control.right { + right: 6% +} + +.testimonial-carousel .carousel-control.right:before { + content: "\203a" +} + +.testimonial-carousel .testimonial { + margin-right: 15%; + margin-left: 15% +} + +.testimonial-carousel .testimonial .avatar { + margin-bottom: 2rem +} + +.testimonial-carousel .testimonial .avatar img { + max-width: 170px +} + +.testimonial-carousel .testimonial h4 { + margin-bottom: 1.3rem; + font-weight: 500 +} + +.testimonial-carousel .testimonial h5 { + margin-bottom: .9rem; + color: #424242; + font-weight: 400 +} + +.testimonial-carousel .testimonial p { + color: #666 +} + +.card-body h3, +.card-body h5 { + font-weight: 400; + margin-bottom: 1rem +} + +.card-body h4 { + font-weight: 500; + margin-bottom: 1rem +} + +.card-body a h5 { + font-size: 1rem +} + +.magazine-section .view { + margin-bottom: 2rem +} + +.magazine-section .single-news { + border-bottom: 1px solid #e0e0e0; + margin-bottom: 1.5rem +} + +.magazine-section .single-news:last-of-type { + border-bottom: none +} + +@media (max-width: 772px) { + .magazine-section .single-news { + padding-bottom: 1rem + } +} + +.magazine-section .single-news .news-data { + margin-bottom: 5rem +} + +.magazine-section .single-news .news-data h6 { + float: left +} + +.magazine-section .single-news .news-data p, +.magazine-section .single-news a .fa-angle-right { + float: right +} + +.magazine-section .single-news h3 { + margin-top: 1.5rem; + margin-bottom: 1.5rem +} + +.magazine-section .single-news a { + color: #424242; + font-weight: 300; + margin-bottom: 1rem +} + +.magazine-section .single-news a:hover { + color: #616161; + -webkit-transition: .2s; + transition: .2s +} + +.magazine-section .single-news p { + color: #757575 +} + +.magazine-section .single-news strong { + font-weight: 500 +} + +.magazine-section.multi-columns h6 { + margin-bottom: 1.5rem; + text-align: center +} + +.magazine-section.multi-columns .view { + margin-bottom: 2rem +} + +.magazine-section.multi-columns .single-news { + padding-bottom: 1rem +} + +.magazine-section.multi-columns .single-news strong { + font-size: 1.2rem +} + +.pricing-card { + text-align: center +} + +.pricing-card p { + font-size: 1rem +} + +.pricing-card ul { + list-style-type: none; + padding: 0 +} + +.pricing-card .header { + border-radius: 6px 6px 0 0; + color: #fff +} + +.pricing-card .header h4 { + padding: 2.5rem; + font-weight: 500 +} + +.pricing-card .price { + position: relative; + padding-top: 3rem +} + +.pricing-card .price h1, +.pricing-card .price h2 { + font-size: 5rem; + padding: 1.5rem; + font-weight: 300 +} + +.pricing-card .price h1:before, +.pricing-card .price h2:before { + content: "$"; + font-size: 30px; + position: absolute; + margin-left: -1.2rem; + margin-top: .7rem +} + +.pricing-card .price h1:after, +.pricing-card .price h2:after { + content: "/mo"; + font-size: 30px; + position: absolute; + margin-top: 3rem +} + +.pricing-card .price .version { + position: absolute; + top: 0; + width: 100%; + background-color: rgba(0, 0, 0, .3); + padding: 1rem +} + +.pricing-card .price .version h5 { + padding: 0; + margin: 0 +} + +.pricing-card .heading h1 { + font-size: 4rem; + font-weight: 400 +} + +.pricing-card .striped { + padding: .6rem +} + +.naked-card .price, +.pricing-card.card-overlay .price { + padding-top: 0 +} + +.pricing-card .striped .fa { + margin-right: 5px +} + +.pricing-card .striped .fa-check { + color: green +} + +.pricing-card .striped .fa-times { + color: red +} + +.pricing-card .striped li { + border-bottom: 1px solid rgba(153, 153, 153, .298039); + margin-bottom: 1rem +} + +.pricing-card.card-overlay { + display: block; + color: #fff +} + +.pricing-card.card-overlay p { + color: #fff +} + +.pricing-card .green-striped li { + border-color: #33c28a +} + +.pricing-card .orange-striped li { + border-color: #e97d63 +} + +.pricing-card .purple-striped li { + border-color: #963c94 +} + +.pricing-card .card-background { + background-color: #28283f; + border-radius: 0 0 6px 6px +} + +.card .card-circle { + border: 2px solid #e0e0e0; + height: 120px; + width: 120px; + margin-bottom: 2rem; + border-radius: 50% +} + +.card .card-circle .fa { + font-size: 4rem +} + +.naked-card h5 { + margin-top: 1.2rem +} + +.form-header { + color: #fff; + text-align: center; + margin-top: -50px; + margin-bottom: 3rem; + padding: 1rem; + border-radius: 2px +} + +.card .card-body h3 { + margin-bottom: 0; + padding: .7rem +} + +.md-form .prefix.grey-text { + font-size: 1.5rem; + margin-top: 1rem +} + +.section .contact-icons { + text-align: center; + list-style-type: none; + padding: 0 +} + +.section .contact-icons li { + margin-bottom: 2.2rem +} + +section .form form .btn-floating { + float: right; + position: relative; + bottom: 3rem; + margin-right: 0 +} + +section .contact { + background-color: #103f6d; + height: 100% +} + +section .contact .contact-icons li i { + float: left; + clear: both; + margin-right: 1rem +} + +section .contact .contact-icons li i.fa { + font-size: 1.5rem +} + +section .contact .contact-icons li p { + padding-top: .5rem; + text-align: left +} + +section .contact i { + color: #6b89a5 +} + +code[class*=language-], +pre[class*=language-] { + color: #292b2c; + background: #eaeaea; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + font-size: .85rem; + -moz-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -ms-hyphens: none; + hyphens: none +} + +:not(pre)>code[class*=language-], +pre[class*=language-] { + background: #eaeaea +} + +pre[class*=language-] { + -webkit-box-shadow: 0 1px 6px 0 rgba(0, 0, 0, .2), 0 1px 6px 0 rgba(0, 0, 0, .19); + box-shadow: 0 1px 6px 0 rgba(0, 0, 0, .2), 0 1px 6px 0 rgba(0, 0, 0, .19); + margin: 2.5em 0; + overflow: auto; + padding: 1em +} + +pre[class*=language-]::-moz-selection { + background: rgba(3, 169, 244, .7) +} + +code[class*=language-]::-moz-selection, +pre[class*=language-]::-moz-selection { + text-shadow: none; + background: rgba(3, 169, 244, .7) +} + +code[class*=language-]::selection, +pre[class*=language-]::selection { + text-shadow: none; + background: rgba(3, 169, 244, .7) +} + +pre[class*=language-] span::-moz-selection { + background: rgba(3, 169, 244, .7) +} + +code[class*=language-] span::-moz-selection, +pre[class*=language-] span::-moz-selection { + text-shadow: none; + background: rgba(3, 169, 244, .7) +} + +code[class*=language-] span::selection, +pre[class*=language-] span::selection { + text-shadow: none; + background: rgba(3, 169, 244, .7) +} + +:not(pre)>code[class*=language-] { + border: .13em solid #545454; + -webkit-box-shadow: 1px 1px .3em -.1em #000 inset; + box-shadow: 1px 1px .3em -.1em #000 inset; + padding: .15em .2em .05em; + white-space: normal +} + +.token.cdata, +.token.comment, +.token.doctype, +.token.prolog { + color: #777 +} + +.namespace, +.token.punctuation { + opacity: .7 +} + +.token.boolean, +.token.deleted, +.token.number, +.token.tag { + color: #ce6849 +} + +.token.tag { + -webkit-box-shadow: none; + box-shadow: none; + text-shadow: none; + font-weight: 400; + display: inline; + padding: 0 +} + +.token.builtin, +.token.constant, +.token.keyword, +.token.property, +.token.selector, +.token.symbol { + color: #328946 +} + +.language-css .token.string, +.style .token.string, +.token.attr-name, +.token.attr-value, +.token.char, +.token.entity, +.token.inserted, +.token.operator, +.token.string, +.token.url, +.token.variable { + color: #b4284f +} + +.token.atrule { + color: #7385a5 +} + +.token.important, +.token.regex { + color: #e8c062 +} + +.token.bold, +.token.important { + font-weight: 700 +} + +.token.italic { + font-style: italic +} + +.token.entity { + cursor: help +} + +pre[data-line] { + padding: 1em 0 1em 3em; + position: relative +} + +.language-markup .token.attr-name, +.language-markup .token.punctuation, +.language-markup .token.tag { + color: #2456a0 +} + +.token { + position: relative; + z-index: 1 +} + +.line-highlight { + background: -webkit-linear-gradient(to right, rgba(84, 84, 84, .1) 70%, rgba(84, 84, 84, 0)); + background: rgba(84, 84, 84, .25); + background: -webkit-gradient(linear, left top, right top, color-stop(70%, rgba(84, 84, 84, .1)), color-stop(70%, rgba(84, 84, 84, 0))); + background: -webkit-linear-gradient(left, rgba(84, 84, 84, .1) 70%, rgba(84, 84, 84, 0)); + background: linear-gradient(to right, rgba(84, 84, 84, .1) 70%, rgba(84, 84, 84, 0)); + border-bottom: 1px dashed #545454; + border-top: 1px dashed #545454; + left: 0; + line-height: inherit; + margin-top: .75em; + padding: inherit 0; + pointer-events: none; + position: absolute; + right: 0; + white-space: pre; + z-index: 0 +} + +.line-highlight:before, +.line-highlight[data-end]:after { + background-color: #8693a6; + border-radius: 999px; + -webkit-box-shadow: 0 1px #fff; + box-shadow: 0 1px #fff; + color: #f4f1ef; + content: attr(data-start); + font: 700 65%/1.5 sans-serif; + left: .6em; + min-width: 1em; + padding: 0 .5em; + position: absolute; + text-align: center; + text-shadow: none; + top: .4em; + vertical-align: .3em +} + +.line-highlight[data-end]:after { + bottom: .4em; + content: attr(data-end); + top: auto +} + +pre.code-toolbar { + position: relative +} + +pre.code-toolbar>.toolbar { + position: absolute; + top: .3em; + right: .3em; + background: #f5f2f0; + background: rgba(224, 224, 224, .2) +} + +pre.code-toolbar>.toolbar a { + color: #6e6e6e; + font-size: .9rem; + cursor: pointer; + padding: 0 .5em; + font-weight: 600 +} + +pre.code-toolbar>.toolbar a.zeroclipboard-is-hover, +pre.code-toolbar>.toolbar a:focus, +pre.code-toolbar>.toolbar a:hover { + color: inherit +} + +.wpcf7-submit, +div.bbp-submit-wrapper button { + line-height: 1.33333; + position: relative; + padding: 5px 22px; + border: 0; + margin: 10px; + cursor: pointer; + border-radius: 2px; + text-transform: uppercase; + text-decoration: none; + outline: 0!important; + color: #fff!important; + -webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12); + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12); + -webkit-transition: .2s ease-out; + transition: .2s ease-out; + background-color: #154771!important +} + +.wpcf7-submit:hover, +div.bbp-submit-wrapper button:hover { + -webkit-box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + background-color: #1d629c!important +} + +.wpcf7-submit:focus, +div.bbp-submit-wrapper button:focus { + background-color: #1d629c!important +} + +@media only screen and (min-width: 992px) { + footer.page-footer .col-md-4 { + margin-left: 2rem + } +} + +.price-select { + margin-left: 30%; + margin-right: 30% +} + +@media only screen and (max-width: 992px) { + .price-select { + margin-left: 25%; + margin-right: 25% + } +} + +@media only screen and (max-width: 768px) { + .price-select { + margin-left: 15%; + margin-right: 15% + } +} + +@media only screen and (max-width: 500px) { + .price-select { + margin-left: 5%; + margin-right: 5% + } +} + +.side-nav .collapsible a { + height: 40px; + line-height: 40px; + margin-bottom: 0 +} + +.side-nav .collapsible .collapsible-body a { + height: 32px; + line-height: 32px +} + +.side-nav .fa-angle-down.rotate-icon { + top: 12px +} + +.side-nav #mdw_main_search { + height: 1.1rem +} + +.side-nav .form-group { + margin-bottom: .7rem +} + +.side-nav .current-menu-item a { + background: #33b5e5 +} + +#menu-item-403, +#menu-item-43627, +#menu-item-43629, +#menu-item-44795 { + border-top: 1px solid rgba(153, 153, 153, .298039) +} + +#bbpress-forums div.bbp-the-content-wrapper textarea.bbp-the-content { + height: 200px +} + +#bbpress-forums #bbp-search-form { + margin-bottom: 2rem +} + +#bbp_search_submit { + border-radius: 0; + border: 0; + -webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12); + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12); + -webkit-transition: .2s ease-out; + transition: .2s ease-out; + color: #fff; + margin: 6px; + background-color: #154771!important; + padding: .6rem 1.05rem; + font-size: 1.05rem; + line-height: 1.11 +} + +#bbp_search_submit:hover { + -webkit-box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + color: #fff +} + +#bbp_search_submit.active, +#bbp_search_submit:active, +#bbp_search_submit:focus { + outline: 0; + color: #fff +} + +#bbp_search_submit:focus, +#bbp_search_submit:hover { + background-color: #1d629c!important +} + +.newsfeed .img-fluid { + width: 100% +} + +.documentation .doc-title { + border-top: 1px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; + padding: 2rem 0; + margin: 5rem 0 2rem; + text-transform: uppercase; + font-size: 2rem +} + +.documentation .doc-title.doc-first { + border-top: none; + margin-top: 0; + padding-top: 1.2rem +} + +.documentation .doc-title.doc-subtitle { + text-transform: none; + border-top: none; + font-size: 1.7rem; + margin-top: 2rem +} + +.documentation .doc-title .btn { + margin-top: -2px +} + +@media (max-width: 776px) { + .documentation .doc-title .btn { + margin-top: 1rem; + display: block + } +} + +.documentation .col-example { + padding: 1rem; + background-color: #33b5e5; + border: 2px solid #fff; + color: #fff; + text-align: center +} + +.documentation .example-td { + padding: 1rem; + background-color: #33b5e5!important; + border: 2px solid #fff!important; + color: #fff +} + +.documentation .example-parent { + background-color: #eee!important +} + +.documentation li.circle-li { + list-style-type: disc +} + +.documentation ul.ul-flex { + padding-left: 3rem +} + +.documentation .is-visible { + background-color: #bbdefb +} + +.documentation .is-hidden { + color: #9e9e9e +} + +.documentation .scroll-box { + position: relative +} + +.documentation .scrollspy-example { + overflow-y: scroll; + position: relative; + height: 200px; + padding: 1rem +} + +.documentation .dzik:after { + content: "Wrrr. jestem wielkim strasznym dzikiem" +} + +.documentation footer { + padding-left: 0 +} + +.color-block, +.color-block-dark { + height: 130px; + padding: 40px; + text-align: center; + color: #fff +} + +.color-block-dark h5 { + font-size: 1rem +} + +.dynamic-color .col-md-4 { + margin-bottom: 2rem +} + +.dynamic-color .col-md-4 div { + padding: 7px 20px +} + +#comments .comment-text { + margin-top: 1rem +} + +#comments button, +#comments html input[type=button], +#comments input[type=reset], +#comments input[type=submit] { + display: inline-block; + padding: .375rem 1rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + text-align: center; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border-radius: 0; + border: 0; + -webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12); + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12); + -webkit-transition: .2s ease-out; + transition: .2s ease-out; + color: #fff; + margin: 6px +} + +.bbp-author-ip, +.variations_form label:not(.active) .fa.fa-check { + display: none +} + +.author-box, +.comments-section { + margin-bottom: 2rem +} + +#comments button:hover, +#comments html input[type=button]:hover, +#comments input[type=reset]:hover, +#comments input[type=submit]:hover { + -webkit-box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + color: #fff +} + +p.form-submit i.btn input[type=submit], +p.form-submit i.btn input[type=submit]:hover { + -webkit-box-shadow: none!important; + box-shadow: none!important +} + +.comments-section { + padding-top: 1rem +} + +#billing_vat_field, +.main-title { + margin-bottom: 1.5rem +} + +.comments-section .avatar { + max-width: 100px!important +} + +.tutorial-content pre.code-toolbar { + max-height: 450px!important +} + +.tutorial-content p { + text-align: justify +} + +input[name=quantity] { + position: absolute; + left: -99999px +} + +.product_meta { + position: absolute; + top: -1000px +} + +.variable_name label { + font-size: 1.3rem +} + +.single_variation span, +p.price { + font-size: 2.5rem +} + +code[class*=language-], +pre[class*=language-] { + max-height: 450px +} + +.mdb-skin-custom .navbar { + color: #fff +} + +.mdb-skin-custom .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.mdb-skin-custom .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.mdb-skin-custom .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #1dade2 +} + +.mdb-skin-custom .page-footer { + background-color: #243a51 +} + +.mdb-skin-custom .side-nav { + background-color: #224562 +} + +.mdb-skin-custom .side-nav .social a:hover .fa { + color: #33b5e5!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.mdb-skin-custom .side-nav .collapsible li { + background-color: transparent +} + +.mdb-skin-custom .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.mdb-skin-custom .side-nav .collapsible li .collapsible-header.active, +.mdb-skin-custom .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(72, 198, 255, .8) +} + +.mdb-skin-custom .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.mdb-skin-custom .side-nav .collapsible li .collapsible-body a:hover { + background-color: transparent; + color: #67d5ff +} + +.mdb-skin-custom .side-nav .fa { + color: #fff +} + +.mdb-skin-custom .side-nav .sidenav-bg.mask-strong:after, +.mdb-skin-custom .side-nav .sidenav-bg:after { + background: rgba(13, 36, 60, .85) +} + +.mdb-skin-custom .side-nav .sidenav-bg.mask-light:after { + background: rgba(13, 36, 60, .65) +} + +.mdb-skin-custom .side-nav .sidenav-bg.mask-slight:after { + background: rgba(13, 36, 60, .5) +} + +.mdb-skin-custom .side-nav .sidenav-bg:after { + z-index: -1 +} + +.mdb-skin-custom .btn-ptc { + background: #08aae6 +} + +.mdb-skin-custom .btn-ptc:focus, +.mdb-skin-custom .btn-ptc:hover { + background-color: #4abde8!important +} + +.mdb-skin-custom .btn-ptc.active { + background-color: #14799e!important +} + +.mdb-skin-custom .btn-dtc { + background: #086fb9 +} + +.mdb-skin-custom .btn-dtc:focus, +.mdb-skin-custom .btn-dtc:hover { + background-color: #1e71ae!important +} + +.mdb-skin-custom .btn-dtc.active { + background-color: #0b2a41!important +} + +.mdb-skin-custom .btn-stc { + background: #083761 +} + +.mdb-skin-custom .btn-stc:focus, +.mdb-skin-custom .btn-stc:hover { + background-color: #114a7d!important +} + +.mdb-skin-custom .btn-stc.active { + background-color: #02080d!important +} + +.mdb-skin-custom .form-header-custom { + background: #1b95c1!important +} + +.angular-skin .navbar { + background-color: #4c576c; + color: #fff +} + +.angular-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active, +.angular-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus, +.angular-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover { + background-color: #1dade2 +} + +.angular-skin .page-footer { + background-color: #4c576c +} + +.angular-skin .side-nav { + background-color: #224562 +} + +.angular-skin .side-nav .social a:hover .fa { + color: #33b5e5!important; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.angular-skin .side-nav .collapsible li { + background-color: transparent +} + +.angular-skin .side-nav .collapsible li .collapsible-header { + color: #fff; + -webkit-transition: all .3s linear; + transition: all .3s linear +} + +.angular-skin .side-nav .collapsible li .collapsible-header.active, +.angular-skin .side-nav .collapsible li .collapsible-header:hover { + background-color: rgba(232, 44, 64, .8) +} + +.angular-skin .side-nav .collapsible li .collapsible-body a { + color: #fff +} + +.angular-skin .side-nav .collapsible li .collapsible-body a:hover { + background-color: transparent; + color: #fc96ad +} + +.angular-skin .side-nav .fa { + color: #fff +} + +.angular-skin .side-nav .sidenav-bg.mask-strong:after, +.angular-skin .side-nav .sidenav-bg:after { + background: rgba(52, 64, 86, .85) +} + +.angular-skin .side-nav .sidenav-bg.mask-light:after { + background: rgba(52, 64, 86, .65) +} + +.angular-skin .side-nav .sidenav-bg.mask-slight:after { + background: rgba(52, 64, 86, .5) +} + +.angular-skin .btn-ptc { + background: #08aae6 +} + +.angular-skin .btn-ptc:focus, +.angular-skin .btn-ptc:hover { + background-color: #4abde8!important +} + +.angular-skin .btn-ptc.active { + background-color: #14799e!important +} + +.angular-skin .btn-dtc { + background: #086fb9 +} + +.angular-skin .btn-dtc:focus, +.angular-skin .btn-dtc:hover { + background-color: #1e71ae!important +} + +.angular-skin .btn-dtc.active { + background-color: #0b2a41!important +} + +.angular-skin .btn-stc { + background: #083761 +} + +.angular-skin .btn-stc:focus, +.angular-skin .btn-stc:hover { + background-color: #114a7d!important +} + +.angular-skin .btn-stc.active { + background-color: #02080d!important +} + +.angular-skin .form-header-custom { + background: #1b95c1!important +} + +#billing_vat_field label { + font-size: 1.2rem; + font-weight: 500 +} + +div.dropdown-wrapper { + position: relative; + width: 100%; + height: 0 +} + +ul.search-dropdown { + position: absolute; + top: -20px; + width: 100%; + background-color: #293a48; + padding: 20px 0; + z-index: 100 +} + +ul.search-dropdown li { + padding: 0 5px +} + +ul.search-dropdown li a { + color: #fff; + line-height: 30px; + height: 30px +} + +ul.search-dropdown li a:hover { + background: rgba(0, 0, 0, .12) +} + +.variations_form label { + width: 100%; + font-size: .7rem; + padding: .85rem 1.5rem +} + +.variations_form .btn-group .btn+.btn { + margin-left: 0!important +} + +@media (min-width: 992px) { + .variations_form label { + width: 50% + } +} + +@media (min-width: 1200px) { + .variations_form label { + width: auto + } +} + +.variations_form label.active .fa { + margin-left: 7px; + font-size: .9rem; + color: #fff +} + +.woocommerce-MyAccount-navigation ul { + padding: .7rem; + margin-left: 1rem; + margin-right: 1rem; + position: relative +} + +.woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link { + display: inline-block +} + +.woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link a { + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + -ms-border-radius: 2px; + -o-border-radius: 2px; + color: #666; + text-align: center; + padding: 10px +} + +.woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link:not(.is-active) a:hover { + background: rgba(158, 158, 158, .3) +} + +.woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link.is-active a { + background: #3F729B; + color: #fff; + -webkit-box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15) +} + +.error404 { + min-height: 100vh; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between +} + +.error404 main { + -webkit-box-flex: 2; + -webkit-flex: 2 0 auto; + -ms-flex: 2 0 auto; + flex: 2 0 auto +} + +#wpadminbar { + top: auto; + bottom: 0 +} + +@media screen and (max-width: 600px) { + #wpadminbar { + position: fixed + } +} + +#wpadminbar .menupop .ab-sub-wrapper, +#wpadminbar .shortlink-input { + bottom: 32px +} + +@media screen and (max-width: 782px) { + #wpadminbar .menupop .ab-sub-wrapper, + #wpadminbar .shortlink-input { + bottom: 46px + } +} + +@media screen and (min-width: 783px) { + .admin-bar.masthead-fixed .site-header { + top: 0 + } +} + +img[alt=amex] { + display: none!important +} + +.header-breadcrumb .breadcrumb-item.active { + color: rgba(255, 255, 255, .65) +} + +.reviews-rating { + display: inline-block; + width: 184px; + height: 28px; + background-image: url(https://mdbootstrap.com/img/Others/stars.png); + background-repeat: no-repeat +} + +.stars-5 { + background-position: -15px -22px +} + +.stars-4 { + background-position: -15px -76px +} + +.stars-3 { + background-position: -15px -134px +} + +.stars-2 { + background-position: -15px -190px +} + +.stars-1 { + background-position: -15px -248px +} + +@media (max-width: 760px) { + .modal-backdrop, + .side-modal { + display: none!important + } +} + +.main-title:before, +.title:before { + display: block; + height: 6rem; + margin-top: -6rem; + visibility: hidden; + content: "" +} + +#scrollspy { + width: 100% +} + +#scrollspy a { + font-size: .9rem +} + +.scrollspy-col { + margin-left: 6% +} + +.main-title { + font-size: 3.5rem +} + +.title { + margin-bottom: 1rem +} + +.fa, +.fa-stack { + display: inline-block +} + +.description { + margin-bottom: 2rem +} + +.related-content-heading { + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; + overflow: visible; + padding-top: .5rem; + padding-bottom: .3125rem; + margin-right: 1rem; + line-height: inherit; + white-space: nowrap +} + +.mdb-sidenav, +.sr-only { + overflow: hidden +} + +.fa.fa-pull-left, +.fa.pull-left { + margin-right: .3em +} + +.side-nav .logo-sn { + padding-bottom: 1rem; + padding-top: 1rem +} + +.side-nav .search-form { + margin-top: 0; + border-top: 1px solid rgba(255, 255, 255, .65) +} + +.side-nav .search-form input[type=text] { + border-bottom: 1px solid rgba(255, 255, 255, .65) +} + +.navbar .notifications-nav .dropdown-menu { + width: 23rem +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + clip: rect(0, 0, 0, 0); + border: 0 +} + +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto +} + +.dwqa-search, +.dwqa-user-block { + margin-bottom: 3rem +} + +.dwqa-search { + margin-right: 1.8rem +} + +.dwqa-sort-by { + margin-top: -20px +} + +.wp-editor-area { + height: 300px +} + +.btn-submit-dwqa, +.dwqa-btn-primary { + font-size: 1rem; + padding: .2rem 1rem; + margin-bottom: 3rem +} + +.dwqa-leaderboard { + list-style: none +} + +.dwqa-leaderboard img { + border-radius: 50%; + -webkit-box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, .18), 0 4px 15px 0 rgba(0, 0, 0, .15); + float: left; + margin-right: 20px +} + +.dwqa-user-header { + font-size: 1.1rem +} + +.dwqa-container .rounded, +.dwqa-container label { + font-weight: 500; + font-size: 1.25rem; + text-align: center +} + +.dwqa-container .rounded { + margin-bottom: 2rem +} \ No newline at end of file diff --git a/Documents/css/nst_master.min.css b/Documents/css/nst_master.min.css new file mode 100644 index 000000000..d5617af9e --- /dev/null +++ b/Documents/css/nst_master.min.css @@ -0,0 +1 @@ +.popover,.tooltip,button,select{text-transform:none}dl,h1,h2,h3,h4,h5,h6,ol,p,pre,ul{margin-top:0}.card,.card-deck,.card-group,.form-inline,.list-group,.modal-content,.navbar-expand,.navbar-expand .navbar-nav,.navbar-nav{-webkit-box-direction:normal}.btn,.card,.hiddendiv,.popover,.tooltip{word-wrap:break-word}.breadcrumb,.carousel-indicators,.dropdown-menu,.dwqa-leaderboard,.nav,.navbar-nav,.pagination,.picker__list{list-style:none}.pswp__container,.pswp__img,.waves-effect,a,html{-webkit-tap-highlight-color:transparent}[tabindex="-1"]:focus,button:focus{outline:0!important}address,dl,ol,p,ul{margin-bottom:1rem}body,caption{text-align:left}dd,h1,h2,h3,h4,h5,h6,label{margin-bottom:.5rem}button,hr,input{overflow:visible}address,legend{line-height:inherit}progress,sub,sup{vertical-align:baseline}pre,textarea{overflow:auto}html,pre{-ms-overflow-style:scrollbar}.btn,.custom-control-indicator{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.btn-outline-danger,.btn-outline-dark,.btn-outline-info,.btn-outline-light,.btn-outline-primary,.btn-outline-secondary,.btn-outline-success,.btn-outline-warning,.btn:not([disabled]):not(.disabled).active,.btn:not([disabled]):not(.disabled):active{background-image:none}.pswp,html{-webkit-text-size-adjust:100%}:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#868e96;--gray-dark:#343a40;--primary:#007bff;--secondary:#868e96;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--font-family-monospace:"SFMono-Regular",Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}@media print{blockquote,img,pre,tr{page-break-inside:avoid}*,::after,::before{text-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #999}thead{display:table-header-group}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}article,aside,dialog,figcaption,figure,footer,header,hgroup,legend,main,nav,section{display:block}label,output{display:inline-block}*,::after,::before{-webkit-box-sizing:border-box;box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%}@-ms-viewport{width:device-width}body{margin:0;font-size:1rem;line-height:1.5;color:#212529;background-color:#fff}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0}abbr[data-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{font-style:normal}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-left:0}blockquote,figure{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0}sub{bottom:-.25em}sup{top:-.5em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-size:1em}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}[role=button],a,area,button,input:not([type=range]),label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#868e96;caption-side:bottom}th{text-align:inherit}button{border-radius:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}fieldset{min-width:0;padding:0;margin:0;border:0}legend{width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;color:inherit;white-space:normal}.badge,.dropdown-header,.dropdown-item,.input-group-addon,.input-group-btn,.navbar-brand{white-space:nowrap}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}.display-1,.display-2,.display-3,.display-4{line-height:1.2}summary{display:list-item}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.2;color:inherit}.blockquote,hr{margin-bottom:1rem}.display-1,.display-2,.display-3,.display-4,.lead{font-weight:300}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem}.display-1{font-size:6rem}.display-2{font-size:5.5rem}.display-3{font-size:4.5rem}.display-4{font-size:3.5rem}hr{margin-top:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:5px}.initialism{font-size:90%;text-transform:uppercase}.blockquote{font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#868e96}code,kbd{font-size:90%}.blockquote-footer::before{content:"\2014 \00A0"}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #ddd;border-radius:.25rem;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.table,pre{margin-bottom:1rem}.figure-caption{font-size:90%;color:#868e96}a>code,pre code{padding:0;color:inherit}code,kbd{padding:.2rem .4rem}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}code{color:#bd4147;background-color:#f8f9fa;border-radius:.25rem}a>code{background-color:inherit}kbd{color:#fff;background-color:#212529;border-radius:.2rem}.table,pre code{background-color:transparent}kbd kbd{padding:0;font-size:100%;font-weight:700}.btn,.btn-link,.dropdown-item{font-weight:400}pre{display:block;font-size:90%;color:#212529}.form-check-input,.form-text,.valid-feedback{margin-top:.25rem}pre code{font-size:inherit;border-radius:0}.container,.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto;width:100%}.pre-scrollable{max-height:340px;overflow-y:scroll}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.row{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.form-control,.form-control-file,.form-control-range,.form-text{display:block}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;-webkit-flex-basis:0;flex-basis:0;-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;-webkit-box-flex:0;-webkit-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-ms-flex:0 0 8.333333%;-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;-webkit-box-flex:0;-webkit-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;-webkit-box-flex:0;-webkit-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;-webkit-box-flex:0;-webkit-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;-webkit-box-ordinal-group:0;-webkit-order:-1;order:-1}.order-1{-ms-flex-order:1;-webkit-box-ordinal-group:2;-webkit-order:1;order:1}.order-2{-ms-flex-order:2;-webkit-box-ordinal-group:3;-webkit-order:2;order:2}.order-3{-ms-flex-order:3;-webkit-box-ordinal-group:4;-webkit-order:3;order:3}.order-4{-ms-flex-order:4;-webkit-box-ordinal-group:5;-webkit-order:4;order:4}.order-5{-ms-flex-order:5;-webkit-box-ordinal-group:6;-webkit-order:5;order:5}.order-6{-ms-flex-order:6;-webkit-box-ordinal-group:7;-webkit-order:6;order:6}.order-7{-ms-flex-order:7;-webkit-box-ordinal-group:8;-webkit-order:7;order:7}.order-8{-ms-flex-order:8;-webkit-box-ordinal-group:9;-webkit-order:8;order:8}.order-9{-ms-flex-order:9;-webkit-box-ordinal-group:10;-webkit-order:9;order:9}.order-10{-ms-flex-order:10;-webkit-box-ordinal-group:11;-webkit-order:10;order:10}.order-11{-ms-flex-order:11;-webkit-box-ordinal-group:12;-webkit-order:11;order:11}.order-12{-ms-flex-order:12;-webkit-box-ordinal-group:13;-webkit-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;-webkit-flex-basis:0;flex-basis:0;-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;-webkit-box-flex:0;-webkit-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-ms-flex:0 0 8.333333%;-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;-webkit-box-flex:0;-webkit-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;-webkit-box-flex:0;-webkit-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;-webkit-box-flex:0;-webkit-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;-webkit-box-ordinal-group:0;-webkit-order:-1;order:-1}.order-sm-1{-ms-flex-order:1;-webkit-box-ordinal-group:2;-webkit-order:1;order:1}.order-sm-2{-ms-flex-order:2;-webkit-box-ordinal-group:3;-webkit-order:2;order:2}.order-sm-3{-ms-flex-order:3;-webkit-box-ordinal-group:4;-webkit-order:3;order:3}.order-sm-4{-ms-flex-order:4;-webkit-box-ordinal-group:5;-webkit-order:4;order:4}.order-sm-5{-ms-flex-order:5;-webkit-box-ordinal-group:6;-webkit-order:5;order:5}.order-sm-6{-ms-flex-order:6;-webkit-box-ordinal-group:7;-webkit-order:6;order:6}.order-sm-7{-ms-flex-order:7;-webkit-box-ordinal-group:8;-webkit-order:7;order:7}.order-sm-8{-ms-flex-order:8;-webkit-box-ordinal-group:9;-webkit-order:8;order:8}.order-sm-9{-ms-flex-order:9;-webkit-box-ordinal-group:10;-webkit-order:9;order:9}.order-sm-10{-ms-flex-order:10;-webkit-box-ordinal-group:11;-webkit-order:10;order:10}.order-sm-11{-ms-flex-order:11;-webkit-box-ordinal-group:12;-webkit-order:11;order:11}.order-sm-12{-ms-flex-order:12;-webkit-box-ordinal-group:13;-webkit-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;-webkit-flex-basis:0;flex-basis:0;-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;-webkit-box-flex:0;-webkit-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-ms-flex:0 0 8.333333%;-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;-webkit-box-flex:0;-webkit-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;-webkit-box-flex:0;-webkit-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;-webkit-box-flex:0;-webkit-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;-webkit-box-ordinal-group:0;-webkit-order:-1;order:-1}.order-md-1{-ms-flex-order:1;-webkit-box-ordinal-group:2;-webkit-order:1;order:1}.order-md-2{-ms-flex-order:2;-webkit-box-ordinal-group:3;-webkit-order:2;order:2}.order-md-3{-ms-flex-order:3;-webkit-box-ordinal-group:4;-webkit-order:3;order:3}.order-md-4{-ms-flex-order:4;-webkit-box-ordinal-group:5;-webkit-order:4;order:4}.order-md-5{-ms-flex-order:5;-webkit-box-ordinal-group:6;-webkit-order:5;order:5}.order-md-6{-ms-flex-order:6;-webkit-box-ordinal-group:7;-webkit-order:6;order:6}.order-md-7{-ms-flex-order:7;-webkit-box-ordinal-group:8;-webkit-order:7;order:7}.order-md-8{-ms-flex-order:8;-webkit-box-ordinal-group:9;-webkit-order:8;order:8}.order-md-9{-ms-flex-order:9;-webkit-box-ordinal-group:10;-webkit-order:9;order:9}.order-md-10{-ms-flex-order:10;-webkit-box-ordinal-group:11;-webkit-order:10;order:10}.order-md-11{-ms-flex-order:11;-webkit-box-ordinal-group:12;-webkit-order:11;order:11}.order-md-12{-ms-flex-order:12;-webkit-box-ordinal-group:13;-webkit-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;-webkit-flex-basis:0;flex-basis:0;-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;-webkit-box-flex:0;-webkit-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-ms-flex:0 0 8.333333%;-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;-webkit-box-flex:0;-webkit-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;-webkit-box-flex:0;-webkit-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;-webkit-box-flex:0;-webkit-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;-webkit-box-ordinal-group:0;-webkit-order:-1;order:-1}.order-lg-1{-ms-flex-order:1;-webkit-box-ordinal-group:2;-webkit-order:1;order:1}.order-lg-2{-ms-flex-order:2;-webkit-box-ordinal-group:3;-webkit-order:2;order:2}.order-lg-3{-ms-flex-order:3;-webkit-box-ordinal-group:4;-webkit-order:3;order:3}.order-lg-4{-ms-flex-order:4;-webkit-box-ordinal-group:5;-webkit-order:4;order:4}.order-lg-5{-ms-flex-order:5;-webkit-box-ordinal-group:6;-webkit-order:5;order:5}.order-lg-6{-ms-flex-order:6;-webkit-box-ordinal-group:7;-webkit-order:6;order:6}.order-lg-7{-ms-flex-order:7;-webkit-box-ordinal-group:8;-webkit-order:7;order:7}.order-lg-8{-ms-flex-order:8;-webkit-box-ordinal-group:9;-webkit-order:8;order:8}.order-lg-9{-ms-flex-order:9;-webkit-box-ordinal-group:10;-webkit-order:9;order:9}.order-lg-10{-ms-flex-order:10;-webkit-box-ordinal-group:11;-webkit-order:10;order:10}.order-lg-11{-ms-flex-order:11;-webkit-box-ordinal-group:12;-webkit-order:11;order:11}.order-lg-12{-ms-flex-order:12;-webkit-box-ordinal-group:13;-webkit-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;-webkit-flex-basis:0;flex-basis:0;-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;-webkit-box-flex:0;-webkit-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-ms-flex:0 0 8.333333%;-webkit-box-flex:0;-webkit-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;-webkit-box-flex:0;-webkit-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;-webkit-box-flex:0;-webkit-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;-webkit-box-flex:0;-webkit-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;-webkit-box-flex:0;-webkit-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;-webkit-box-flex:0;-webkit-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;-webkit-box-flex:0;-webkit-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;-webkit-box-flex:0;-webkit-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;-webkit-box-flex:0;-webkit-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;-webkit-box-flex:0;-webkit-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;-webkit-box-flex:0;-webkit-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;-webkit-box-flex:0;-webkit-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;-webkit-box-ordinal-group:0;-webkit-order:-1;order:-1}.order-xl-1{-ms-flex-order:1;-webkit-box-ordinal-group:2;-webkit-order:1;order:1}.order-xl-2{-ms-flex-order:2;-webkit-box-ordinal-group:3;-webkit-order:2;order:2}.order-xl-3{-ms-flex-order:3;-webkit-box-ordinal-group:4;-webkit-order:3;order:3}.order-xl-4{-ms-flex-order:4;-webkit-box-ordinal-group:5;-webkit-order:4;order:4}.order-xl-5{-ms-flex-order:5;-webkit-box-ordinal-group:6;-webkit-order:5;order:5}.order-xl-6{-ms-flex-order:6;-webkit-box-ordinal-group:7;-webkit-order:6;order:6}.order-xl-7{-ms-flex-order:7;-webkit-box-ordinal-group:8;-webkit-order:7;order:7}.order-xl-8{-ms-flex-order:8;-webkit-box-ordinal-group:9;-webkit-order:8;order:8}.order-xl-9{-ms-flex-order:9;-webkit-box-ordinal-group:10;-webkit-order:9;order:9}.order-xl-10{-ms-flex-order:10;-webkit-box-ordinal-group:11;-webkit-order:10;order:10}.order-xl-11{-ms-flex-order:11;-webkit-box-ordinal-group:12;-webkit-order:11;order:11}.order-xl-12{-ms-flex-order:12;-webkit-box-ordinal-group:13;-webkit-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;max-width:100%}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #e9ecef}.table thead th{vertical-align:bottom;border-bottom:2px solid #e9ecef}.table tbody+tbody{border-top:2px solid #e9ecef}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #e9ecef}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#dddfe2}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#cfd2d6}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th,.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#212529;border-color:#32383e}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#e9ecef}.table-dark{color:#fff;background-color:#212529}.table-dark td,.table-dark th,.table-dark thead th{border-color:#32383e}.table-dark.table-bordered,.table-responsive.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media (max-width:575px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm.table-bordered{border:0}}@media (max-width:767px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md.table-bordered{border:0}}@media (max-width:991px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg.table-bordered{border:0}}@media (max-width:1199px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.collapsing,.modal,.modal-open{overflow:hidden}.form-control{width:100%;color:#495057;background-clip:padding-box;border:1px solid #ced4da;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0}.form-control::-ms-input-placeholder{color:#868e96;opacity:1}.form-control::-webkit-input-placeholder{color:#868e96;opacity:1}.form-control::-moz-placeholder{color:#868e96;opacity:1}.form-control:-ms-input-placeholder{color:#868e96;opacity:1}.form-control::placeholder{color:#868e96;opacity:1}.form-control:disabled,.form-control[readonly]{opacity:1}select.form-control:not([size]):not([multiple]){height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px)}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.col-form-label{padding-top:-webkit-calc(.375rem + 1px);padding-top:calc(.375rem + 1px);padding-bottom:-webkit-calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;line-height:1.5}.col-form-label-lg{padding-top:-webkit-calc(.5rem + 1px);padding-top:calc(.5rem + 1px);padding-bottom:-webkit-calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:-webkit-calc(.25rem + 1px);padding-top:calc(.25rem + 1px);padding-bottom:-webkit-calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.col-form-legend,.form-control-plaintext{padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0}.col-form-legend{font-size:1rem}.form-control-plaintext{line-height:1.5;background-color:transparent;border:solid transparent;border-width:1px 0}.custom-file-input.is-valid~.custom-file-control,.custom-select.is-valid,.form-control.is-valid,.was-validated .custom-file-input:valid~.custom-file-control,.was-validated .custom-select:valid,.was-validated .form-control:valid{border-color:#28a745}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm,.input-group-lg>.form-control-plaintext.form-control,.input-group-lg>.form-control-plaintext.input-group-addon,.input-group-lg>.input-group-btn>.form-control-plaintext.btn,.input-group-sm>.form-control-plaintext.form-control,.input-group-sm>.form-control-plaintext.input-group-addon,.input-group-sm>.input-group-btn>.form-control-plaintext.btn{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-sm>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),.input-group-sm>select.input-group-addon:not([size]):not([multiple]),select.form-control-sm:not([size]):not([multiple]){height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px)}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-lg>.input-group-btn>select.btn:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),.input-group-lg>select.input-group-addon:not([size]):not([multiple]),select.form-control-lg:not([size]):not([multiple]){height:-webkit-calc(2.875rem + 2px);height:calc(2.875rem + 2px)}.form-group{margin-bottom:1rem}.form-row{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;margin-bottom:.5rem}.form-check.disabled .form-check-label{color:#868e96}.form-check-label{padding-left:1.25rem;margin-bottom:0}.invalid-tooltip,.valid-tooltip{position:absolute;top:100%;z-index:5;width:250px;padding:.5rem;line-height:1;border-radius:.2rem}.form-check-input{position:absolute;margin-left:-1.25rem}.form-check-inline{display:inline-block;margin-right:.75rem}.valid-feedback,.valid-tooltip{display:none;font-size:.875rem}.form-check-inline .form-check-label{vertical-align:middle}.valid-feedback{color:#28a745}.valid-tooltip{margin-top:.1rem;color:#fff;background-color:rgba(40,167,69,.8)}.custom-control-input.is-valid~.custom-control-description,.form-check-input.is-valid+.form-check-label,.was-validated .custom-control-input:valid~.custom-control-description,.was-validated .form-check-input:valid+.form-check-label{color:#28a745}.custom-select.is-valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.was-validated .form-control:valid:focus{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-indicator,.was-validated .custom-control-input:valid~.custom-control-indicator{background-color:rgba(40,167,69,.25)}.custom-file-input.is-valid~.custom-file-control::before,.was-validated .custom-file-input:valid~.custom-file-control::before{border-color:inherit}.custom-file-input.is-invalid~.custom-file-control,.custom-select.is-invalid,.form-control.is-invalid,.was-validated .custom-file-input:invalid~.custom-file-control,.was-validated .custom-select:invalid,.was-validated .form-control:invalid{border-color:#dc3545}.custom-file-input.is-valid:focus,.was-validated .custom-file-input:valid:focus{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.25);box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;margin-top:.25rem;font-size:.875rem;color:#dc3545}.invalid-tooltip{display:none;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:rgba(220,53,69,.8)}.custom-control-input.is-invalid~.custom-control-description,.form-check-input.is-invalid+.form-check-label,.was-validated .custom-control-input:invalid~.custom-control-description,.was-validated .form-check-input:invalid+.form-check-label{color:#dc3545}.custom-select.is-invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.was-validated .form-control:invalid:focus{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-indicator,.was-validated .custom-control-input:invalid~.custom-control-indicator{background-color:rgba(220,53,69,.25)}.custom-file-input.is-invalid~.custom-file-control::before,.was-validated .custom-file-input:invalid~.custom-file-control::before{border-color:inherit}.custom-file-input.is-invalid:focus,.was-validated .custom-file-input:invalid:focus{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;margin-bottom:0}.form-inline .form-check,.form-inline .form-group{margin-bottom:0}.form-inline .form-group{display:flex;-ms-flex:0 0 auto;-webkit-box-flex:0;-webkit-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group{width:auto}.form-inline .form-check{display:flex;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;width:auto;margin-top:0}.form-inline .form-check-label{padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;padding-left:0}.form-inline .custom-control-indicator{position:static;display:inline-block;margin-right:.25rem;vertical-align:text-bottom}.form-inline .has-feedback .form-control-feedback{top:0}}.card,.card-deck,.navbar-nav{-webkit-box-orient:vertical}.btn-group-vertical,.custom-controls-stacked{-webkit-box-orient:vertical;-webkit-box-direction:normal}.btn-block,input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.collapsing,.dropdown,.dropup{position:relative}.btn{display:inline-block;text-align:center;vertical-align:middle;user-select:none;line-height:1.5}.btn:focus,.btn:hover{text-decoration:none}.btn.focus,.btn:focus{outline:0;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-primary{color:#fff;border-color:#007bff}.btn-primary:hover{color:#fff;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-primary.disabled,.btn-primary:disabled{background-color:#007bff;border-color:#007bff}.btn-primary:not([disabled]):not(.disabled).active,.btn-primary:not([disabled]):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-secondary{color:#fff;border-color:#868e96}.btn-secondary:hover{color:#fff;border-color:#6c757d}.btn-secondary.focus,.btn-secondary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(134,142,150,.5);box-shadow:0 0 0 .2rem rgba(134,142,150,.5)}.btn-secondary:not([disabled]):not(.disabled).active,.btn-secondary:not([disabled]):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#666e76;-webkit-box-shadow:0 0 0 .2rem rgba(134,142,150,.5);box-shadow:0 0 0 .2rem rgba(134,142,150,.5)}.btn-success{color:#fff;border-color:#28a745}.btn-success:hover{color:#fff;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-success.disabled,.btn-success:disabled{background-color:#28a745;border-color:#28a745}.btn-success:not([disabled]):not(.disabled).active,.btn-success:not([disabled]):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-info{color:#fff;border-color:#17a2b8}.btn-info:hover{color:#fff;border-color:#117a8b}.btn-info.focus,.btn-info:focus{-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-info.disabled,.btn-info:disabled{background-color:#17a2b8;border-color:#17a2b8}.btn-info:not([disabled]):not(.disabled).active,.btn-info:not([disabled]):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f;-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-warning{color:#111;border-color:#ffc107}.btn-warning:hover{color:#111;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-warning.disabled,.btn-warning:disabled{background-color:#ffc107;border-color:#ffc107}.btn-warning:not([disabled]):not(.disabled).active,.btn-warning:not([disabled]):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#111;background-color:#d39e00;border-color:#c69500;-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-danger{color:#fff;border-color:#dc3545}.btn-danger:hover{color:#fff;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-danger.disabled,.btn-danger:disabled{background-color:#dc3545;border-color:#dc3545}.btn-danger:not([disabled]):not(.disabled).active,.btn-danger:not([disabled]):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-light{color:#111;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#111;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-light.disabled,.btn-light:disabled{background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not([disabled]):not(.disabled).active,.btn-light:not([disabled]):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#111;background-color:#dae0e5;border-color:#d3d9df;-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-dark.disabled,.btn-dark:disabled{background-color:#343a40;border-color:#343a40}.btn-dark:not([disabled]):not(.disabled).active,.btn-dark:not([disabled]):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d;-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-primary.focus,.btn-outline-primary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not([disabled]):not(.disabled).active,.btn-outline-primary:not([disabled]):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff;-webkit-box-shadow:0 0 0 .2rem rgba(0,123,255,.5);box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary.focus,.btn-outline-secondary:focus{-webkit-box-shadow:0 0 0 .2rem rgba(134,142,150,.5);box-shadow:0 0 0 .2rem rgba(134,142,150,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#868e96;background-color:transparent}.btn-outline-secondary:not([disabled]):not(.disabled).active,.btn-outline-secondary:not([disabled]):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#868e96;border-color:#868e96;-webkit-box-shadow:0 0 0 .2rem rgba(134,142,150,.5);box-shadow:0 0 0 .2rem rgba(134,142,150,.5)}.btn-outline-success.focus,.btn-outline-success:focus{-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not([disabled]):not(.disabled).active,.btn-outline-success:not([disabled]):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745;-webkit-box-shadow:0 0 0 .2rem rgba(40,167,69,.5);box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info.focus,.btn-outline-info:focus{-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not([disabled]):not(.disabled).active,.btn-outline-info:not([disabled]):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8;-webkit-box-shadow:0 0 0 .2rem rgba(23,162,184,.5);box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning.focus,.btn-outline-warning:focus{-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not([disabled]):not(.disabled).active,.btn-outline-warning:not([disabled]):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#fff;background-color:#ffc107;border-color:#ffc107;-webkit-box-shadow:0 0 0 .2rem rgba(255,193,7,.5);box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger.focus,.btn-outline-danger:focus{-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not([disabled]):not(.disabled).active,.btn-outline-danger:not([disabled]):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.5);box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;background-color:transparent;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not([disabled]):not(.disabled).active,.btn-outline-light:not([disabled]):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa;-webkit-box-shadow:0 0 0 .2rem rgba(248,249,250,.5);box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;background-color:transparent;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not([disabled]):not(.disabled).active,.btn-outline-dark:not([disabled]):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40;-webkit-box-shadow:0 0 0 .2rem rgba(52,58,64,.5);box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link:hover{color:#0056b3;text-decoration:underline;border-color:transparent}.btn-link.focus,.btn-link:focus{border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#868e96}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block}.btn-block+.btn-block{margin-top:.5rem}.dropdown-toggle::after,.dropup .dropdown-toggle::after{width:0;vertical-align:.255em;content:"";height:0}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.show{opacity:1}.collapse{display:none}.collapse.show{display:block}tr.collapse.show{display:table-row}tbody.collapse.show{display:table-row-group}.collapsing{height:0;-webkit-transition:height .35s ease;transition:height .35s ease}.dropdown-toggle::after{display:inline-block;margin-left:.255em;border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropup .dropdown-menu{margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;color:#212529;text-align:inherit;background:0 0;border:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn,.btn-group-vertical>.btn:not(:first-child):not(:last-child),.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn,.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle),.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#868e96;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#868e96}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:-webkit-inline-box;display:-webkit-inline-flex;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:0 1 auto;-webkit-box-flex:0;-webkit-flex:0 1 auto;flex:0 1 auto}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn+.dropdown-toggle-split::after,.btn-group>.btn:first-child{margin-left:0}.btn-toolbar{display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn+.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column;-ms-flex-align:start;-webkit-box-align:start;-webkit-align-items:flex-start;align-items:flex-start;-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.custom-control,.input-group,.input-group-btn,.input-group-btn>.btn{position:relative}.input-group{display:flex;-ms-flex-align:stretch;-webkit-box-align:stretch;-webkit-align-items:stretch;align-items:stretch;width:100%}.input-group .form-control{position:relative;z-index:2;-ms-flex:1 1 auto;-webkit-box-flex:1;-webkit-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group .form-control:active,.input-group .form-control:focus,.input-group .form-control:hover,.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:3}.input-group .form-control,.input-group-addon,.input-group-btn{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.input-group-addon{padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.alert-link,.badge,.close{font-weight:700}.input-group-addon.form-control-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:.25rem .5rem;font-size:.875rem;border-radius:.2rem}.input-group-addon.form-control-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:.3rem}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:not(:last-child),.input-group-addon:not(:last-child),.input-group-btn:not(:first-child)>.btn-group:not(:last-child)>.btn,.input-group-btn:not(:first-child)>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group>.btn,.input-group-btn:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:not(:last-child){border-right:0}.input-group .form-control:not(:first-child),.input-group-addon:not(:first-child),.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group>.btn,.input-group-btn:not(:first-child)>.dropdown-toggle,.input-group-btn:not(:last-child)>.btn-group:not(:first-child)>.btn,.input-group-btn:not(:last-child)>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.form-control+.input-group-addon:not(:first-child){border-left:0}.input-group-btn{-ms-flex-align:stretch;-webkit-box-align:stretch;-webkit-align-items:stretch;align-items:stretch;font-size:0}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn:first-child>.btn+.btn{margin-left:0}.input-group-btn:not(:last-child)>.btn,.input-group-btn:not(:last-child)>.btn-group{margin-right:-1px}.input-group-btn:not(:first-child)>.btn,.input-group-btn:not(:first-child)>.btn-group{z-index:2;margin-left:0}.input-group-btn:not(:first-child)>.btn-group:first-child,.input-group-btn:not(:first-child)>.btn:first-child{margin-left:-1px}.card>hr,.custom-controls-stacked .custom-control+.custom-control{margin-left:0}.input-group-btn:not(:first-child)>.btn-group:active,.input-group-btn:not(:first-child)>.btn-group:focus,.input-group-btn:not(:first-child)>.btn-group:hover,.input-group-btn:not(:first-child)>.btn:active,.input-group-btn:not(:first-child)>.btn:focus,.input-group-btn:not(:first-child)>.btn:hover{z-index:3}.custom-control{display:-ms-inline-flexbox;display:-webkit-inline-box;display:-webkit-inline-flex;display:inline-flex;min-height:1.5rem;padding-left:1.5rem;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-indicator{color:#fff;background-color:#007bff}.custom-control-input:focus~.custom-control-indicator{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25);box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:active~.custom-control-indicator{color:#fff;background-color:#b3d7ff}.custom-control-input:disabled~.custom-control-indicator{background-color:#e9ecef}.custom-control-input:disabled~.custom-control-description{color:#868e96}.custom-control-indicator{position:absolute;top:.25rem;left:0;display:block;width:1rem;height:1rem;pointer-events:none;user-select:none;background-color:#ddd;background-repeat:no-repeat;background-position:center center;background-size:50% 50%}.custom-file-control,.waves-effect{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.custom-checkbox .custom-control-indicator{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-indicator{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-indicator{background-color:#007bff;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-radio .custom-control-indicator{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-indicator{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-controls-stacked{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.custom-file,.custom-select{display:inline-block;max-width:100%}.custom-controls-stacked .custom-control{margin-bottom:.25rem}.custom-select{height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.5;color:#495057;vertical-align:middle;background:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") right .75rem center no-repeat #fff;background-size:8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.pswp__button,[type=reset],[type=submit],button,button.close,html [type=button],input[type=range]{-webkit-appearance:none}.custom-select:focus{border-color:#80bdff;outline:0}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple]{height:auto;background-image:none}.custom-select:disabled{color:#868e96;background-color:#e9ecef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:-webkit-calc(1.8125rem + 2px);height:calc(1.8125rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-file{position:relative;height:calc(2.25rem + 2px);margin-bottom:0}.custom-file-control,.custom-file-control::before{position:absolute;padding:.375rem .75rem;line-height:1.5;color:#495057}.custom-file-input{min-width:14rem;max-width:100%;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-control{-webkit-box-shadow:0 0 0 .075rem #fff,0 0 0 .2rem #007bff;box-shadow:0 0 0 .075rem #fff,0 0 0 .2rem #007bff}.custom-file-control{top:0;right:0;left:0;z-index:5;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);pointer-events:none;user-select:none;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-control:lang(en):empty::after{content:"Choose file..."}.custom-file-control::before{top:-1px;right:-1px;bottom:-1px;z-index:6;display:block;height:-webkit-calc(2.25rem + 2px);height:calc(2.25rem + 2px);background-color:#e9ecef;border:1px solid #ced4da;border-radius:0 .25rem .25rem 0}.nav,.navbar{-ms-flex-wrap:wrap}.custom-file-control:lang(en)::before{content:"Browse"}.nav{display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0}.nav-link,.navbar{padding:.5rem 1rem}.nav-link{display:block}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#868e96}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #ddd}.nav-tabs .nav-link.disabled{color:#868e96;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#ddd #ddd #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;-webkit-box-flex:1;-webkit-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;-webkit-flex-basis:0;flex-basis:0;-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-pack:justify;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.navbar>.container,.navbar>.container-fluid{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-pack:justify;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.navbar-expand,.navbar-expand .navbar-nav{-webkit-box-orient:horizontal}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;-ms-flex-positive:1;-webkit-box-flex:1;-webkit-flex-grow:1;flex-grow:1;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background:0 0;border:1px solid transparent}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:center center no-repeat;background-size:100% 100%}@media (max-width:575px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm,.navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal}.navbar-expand-sm{-ms-flex-flow:row nowrap;-webkit-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important;-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .dropup .dropdown-menu{top:auto;bottom:100%}}@media (max-width:767px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md,.navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal}.navbar-expand-md{-ms-flex-flow:row nowrap;-webkit-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important;-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .dropup .dropdown-menu{top:auto;bottom:100%}}@media (max-width:991px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg,.navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal}.navbar-expand-lg{-ms-flex-flow:row nowrap;-webkit-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important;-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .dropup .dropdown-menu{top:auto;bottom:100%}}@media (max-width:1199px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl,.navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal}.navbar-expand-xl{-ms-flex-flow:row nowrap;-webkit-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important;-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .dropup .dropdown-menu{top:auto;bottom:100%}}.navbar-expand{-ms-flex-flow:row nowrap;-webkit-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;-webkit-box-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important;-ms-flex-preferred-size:auto;-webkit-flex-basis:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .dropup .dropdown-menu{top:auto;bottom:100%}.modal,.modal-backdrop,.popover.bs-popover-auto[x-placement^=top] .arrow,.popover.bs-popover-top .arrow,.tooltip.bs-tooltip-auto[x-placement^=top] .arrow,.tooltip.bs-tooltip-top .arrow{bottom:0}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column;min-width:0;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125)}.card>hr{margin-right:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;-webkit-box-flex:1;-webkit-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-footer,.card-header{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03)}.card-title{margin-bottom:.75rem}.card-header,.card-subtitle,.card-text:last-child{margin-bottom:0}.card-subtitle{margin-top:-.375rem}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header-pills,.card-header-tabs{margin-right:-.625rem;margin-left:-.625rem}.card-header{border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:-webkit-calc(.25rem - 1px) -webkit-calc(.25rem - 1px) 0 0;border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 -webkit-calc(.25rem - 1px) -webkit-calc(.25rem - 1px);border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-bottom:-.75rem;border-bottom:0}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.alert,.btn .badge,.page-link{position:relative}.card-img{width:100%;border-radius:-webkit-calc(.25rem - 1px);border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:-webkit-calc(.25rem - 1px);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:-webkit-calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:-webkit-calc(.25rem - 1px);border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:-webkit-calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck,.card-deck .card{-webkit-box-direction:normal}.card-deck{-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex:1 0 0%;-webkit-box-flex:1;-webkit-flex:1 0 0%;flex:1 0 0%;-ms-flex-direction:column;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group,.list-group{-ms-flex-direction:column}.card-group{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}.card-group .card{margin-bottom:15px}@media (min-width:576px){.card-group{-ms-flex-flow:row wrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;flex-flow:row wrap}.card-group .card{-ms-flex:1 0 0%;-webkit-box-flex:1;-webkit-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group .card+.card{margin-left:0;border-left:0}.card-group .card:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group .card:first-child .card-img-top{border-top-right-radius:0}.card-group .card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group .card:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group .card:last-child .card-img-top{border-top-left-radius:0}.card-group .card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group .card:only-child{border-radius:.25rem}.card-group .card:only-child .card-img-top{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-group .card:only-child .card-img-bottom{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-group .card:not(:first-child):not(:last-child):not(:only-child),.card-group .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top{border-radius:0}.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem}.card-columns .card{display:inline-block;width:100%}}.list-group,.modal-content{-webkit-box-orient:vertical}.breadcrumb,.pagination{border-radius:.25rem}.card-columns .card{margin-bottom:.75rem}.breadcrumb{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;background-color:#e9ecef}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;padding-left:.5rem;color:#868e96;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#868e96}.pagination{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;padding-left:0}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#868e96;pointer-events:none;background-color:#fff;border-color:#ddd}.page-link{display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #ddd}.page-link:focus,.page-link:hover{color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#ddd}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.badge,.close{line-height:1}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;text-align:center;vertical-align:baseline}.badge:empty{display:none}.btn .badge{top:-1px}.badge-primary{color:#fff}.badge-primary[href]:focus,.badge-primary[href]:hover{color:#fff;text-decoration:none;background-color:#0062cc}.badge-secondary{color:#fff}.badge-secondary[href]:focus,.badge-secondary[href]:hover{color:#fff;text-decoration:none;background-color:#6c757d}.badge-success{color:#fff}.badge-success[href]:focus,.badge-success[href]:hover{color:#fff;text-decoration:none;background-color:#1e7e34}.badge-info{color:#fff}.badge-info[href]:focus,.badge-info[href]:hover{color:#fff;text-decoration:none;background-color:#117a8b}.badge-warning[href]:focus,.badge-warning[href]:hover{color:#111;text-decoration:none;background-color:#d39e00}.badge-danger{color:#fff}.badge-danger[href]:focus,.badge-danger[href]:hover{color:#fff;text-decoration:none;background-color:#bd2130}.badge-light{color:#111;background-color:#f8f9fa}.badge-light[href]:focus,.badge-light[href]:hover{color:#111;text-decoration:none;background-color:#dae0e5}.badge-dark{color:#fff;background-color:#343a40}.badge-dark[href]:focus,.badge-dark[href]:hover{color:#fff;text-decoration:none;background-color:#1d2124}.jumbotron{margin-bottom:2rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#464a4e;background-color:#e7e8ea;border-color:#dddfe2}.alert-secondary hr{border-top-color:#cfd2d6}.alert-secondary .alert-link{color:#2e3133}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{font-size:.75rem;border-radius:.25rem}.progress-bar{display:flex;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;color:#fff;background-color:#007bff}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:flex;-ms-flex-align:start;-webkit-box-align:start;-webkit-align-items:flex-start;align-items:flex-start}.media-body{-ms-flex:1;-webkit-box-flex:1;-webkit-flex:1;flex:1}.list-group{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:focus,.list-group-item:hover{text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#868e96;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}a.list-group-item-primary,button.list-group-item-primary{color:#004085}a.list-group-item-primary:focus,a.list-group-item-primary:hover,button.list-group-item-primary:focus,button.list-group-item-primary:hover{color:#004085;background-color:#9fcdff}a.list-group-item-primary.active,button.list-group-item-primary.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#464a4e;background-color:#dddfe2}a.list-group-item-secondary,button.list-group-item-secondary{color:#464a4e}a.list-group-item-secondary:focus,a.list-group-item-secondary:hover,button.list-group-item-secondary:focus,button.list-group-item-secondary:hover{color:#464a4e;background-color:#cfd2d6}a.list-group-item-secondary.active,button.list-group-item-secondary.active{color:#fff;background-color:#464a4e;border-color:#464a4e}.list-group-item-success{color:#155724;background-color:#c3e6cb}a.list-group-item-success,button.list-group-item-success{color:#155724}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#155724;background-color:#b1dfbb}a.list-group-item-success.active,button.list-group-item-success.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}a.list-group-item-info,button.list-group-item-info{color:#0c5460}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#0c5460;background-color:#abdde5}a.list-group-item-info.active,button.list-group-item-info.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}a.list-group-item-warning,button.list-group-item-warning{color:#856404}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#856404;background-color:#ffe8a1}a.list-group-item-warning.active,button.list-group-item-warning.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}a.list-group-item-danger,button.list-group-item-danger{color:#721c24}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#721c24;background-color:#f1b0b7}a.list-group-item-danger.active,button.list-group-item-danger.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}a.list-group-item-light,button.list-group-item-light{color:#818182}a.list-group-item-light:focus,a.list-group-item-light:hover,button.list-group-item-light:focus,button.list-group-item-light:hover{color:#818182;background-color:#ececf6}a.list-group-item-light.active,button.list-group-item-light.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}a.list-group-item-dark,button.list-group-item-dark{color:#1b1e21}a.list-group-item-dark:focus,a.list-group-item-dark:hover,button.list-group-item-dark:focus,button.list-group-item-dark:hover{color:#1b1e21;background-color:#b9bbbe}a.list-group-item-dark.active,button.list-group-item-dark.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.popover,.tooltip{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-style:normal;font-weight:400;letter-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;text-decoration:none;word-spacing:normal;word-break:normal}.modal-title,.popover,.tooltip{line-height:1.5}.popover,.text-hide,.tooltip{text-shadow:none}.close:focus,.close:hover{color:#000;text-decoration:none;opacity:.75}button.close{padding:0;background:0 0;border:0}.modal-content,.popover{background-clip:padding-box}.modal{position:fixed;top:0;right:0;left:0;z-index:1050;display:none;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.show .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px;pointer-events:none}.modal-content{position:relative;display:flex;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column;pointer-events:auto;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.flex-column,.flex-row{-webkit-box-direction:normal!important}.modal-backdrop{position:fixed;top:0;right:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;-ms-flex-align:start;-webkit-box-align:start;-webkit-align-items:flex-start;align-items:flex-start;-ms-flex-pack:justify;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;padding:15px;border-bottom:1px solid #e9ecef;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:15px;margin:-15px -15px -15px auto}.modal-title{margin-bottom:0}.modal-body{position:relative;-ms-flex:1 1 auto;-webkit-box-flex:1;-webkit-flex:1 1 auto;flex:1 1 auto;padding:15px}.modal-footer{display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-pack:end;-webkit-box-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;padding:15px;border-top:1px solid #e9ecef}.popover,.popover .arrow,.popover .arrow::after,.popover .arrow::before,.tooltip,.tooltip .arrow{position:absolute;display:block}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}.popover.bs-popover-auto[x-placement^=bottom] .arrow,.popover.bs-popover-bottom .arrow,.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow,.tooltip.bs-tooltip-bottom .arrow{top:0}@media (min-width:576px){.modal-dialog{max-width:500px;margin:30px auto}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:800px}}.tooltip{z-index:1070;margin:0;text-align:left;text-align:start;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{width:5px;height:5px}.tooltip .arrow::before{position:absolute;border-color:transparent;border-style:solid}.tooltip.bs-tooltip-auto[x-placement^=top],.tooltip.bs-tooltip-top{padding:5px 0}.tooltip.bs-tooltip-auto[x-placement^=top] .arrow::before,.tooltip.bs-tooltip-top .arrow::before{margin-left:-3px;content:"";border-width:5px 5px 0;border-top-color:#000}.tooltip.bs-tooltip-auto[x-placement^=right],.tooltip.bs-tooltip-right{padding:0 5px}.tooltip.bs-tooltip-auto[x-placement^=right] .arrow,.tooltip.bs-tooltip-right .arrow{left:0}.tooltip.bs-tooltip-auto[x-placement^=right] .arrow::before,.tooltip.bs-tooltip-right .arrow::before{margin-top:-3px;content:"";border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.bs-tooltip-auto[x-placement^=bottom],.tooltip.bs-tooltip-bottom{padding:5px 0}.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.tooltip.bs-tooltip-bottom .arrow::before{margin-left:-3px;content:"";border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bs-tooltip-auto[x-placement^=left],.tooltip.bs-tooltip-left{padding:0 5px}.tooltip.bs-tooltip-auto[x-placement^=left] .arrow,.tooltip.bs-tooltip-left .arrow{right:0}.tooltip.bs-tooltip-auto[x-placement^=left] .arrow::before,.tooltip.bs-tooltip-left .arrow::before{right:0;margin-top:-3px;content:"";border-width:5px 0 5px 5px;border-left-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{top:0;left:0;z-index:1060;max-width:276px;text-align:left;text-align:start;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{width:.8rem;height:.4rem}.popover .arrow::after,.popover .arrow::before{border-color:transparent;border-style:solid;content:"";border-width:.8rem}.popover.bs-popover-auto[x-placement^=top],.popover.bs-popover-top{margin-bottom:.8rem}.popover.bs-popover-auto[x-placement^=top] .arrow::after,.popover.bs-popover-auto[x-placement^=top] .arrow::before,.popover.bs-popover-top .arrow::after,.popover.bs-popover-top .arrow::before{border-bottom-width:0}.popover.bs-popover-auto[x-placement^=top] .arrow::before,.popover.bs-popover-top .arrow::before{bottom:-.8rem;margin-left:-.8rem;border-top-color:rgba(0,0,0,.25)}.popover.bs-popover-auto[x-placement^=top] .arrow::after,.popover.bs-popover-top .arrow::after{bottom:-webkit-calc((.8rem - 1px) * -1);bottom:calc((.8rem - 1px) * -1);margin-left:-.8rem;border-top-color:#fff}.popover.bs-popover-auto[x-placement^=right],.popover.bs-popover-right{margin-left:.8rem}.popover.bs-popover-auto[x-placement^=right] .arrow,.popover.bs-popover-right .arrow{left:0}.popover.bs-popover-auto[x-placement^=right] .arrow::after,.popover.bs-popover-auto[x-placement^=right] .arrow::before,.popover.bs-popover-right .arrow::after,.popover.bs-popover-right .arrow::before{margin-top:-.8rem;border-left-width:0}.popover.bs-popover-auto[x-placement^=right] .arrow::before,.popover.bs-popover-right .arrow::before{left:-.8rem;border-right-color:rgba(0,0,0,.25)}.popover.bs-popover-auto[x-placement^=right] .arrow::after,.popover.bs-popover-right .arrow::after{left:-webkit-calc((.8rem - 1px) * -1);left:calc((.8rem - 1px) * -1);border-right-color:#fff}.popover.bs-popover-auto[x-placement^=bottom],.popover.bs-popover-bottom{margin-top:.8rem}.popover.bs-popover-auto[x-placement^=bottom] .arrow::after,.popover.bs-popover-auto[x-placement^=bottom] .arrow::before,.popover.bs-popover-bottom .arrow::after,.popover.bs-popover-bottom .arrow::before{margin-left:-.8rem;border-top-width:0}.popover.bs-popover-auto[x-placement^=bottom] .arrow::before,.popover.bs-popover-bottom .arrow::before{top:-.8rem;border-bottom-color:rgba(0,0,0,.25)}.popover.bs-popover-auto[x-placement^=bottom] .arrow::after,.popover.bs-popover-bottom .arrow::after{top:-webkit-calc((.8rem - 1px) * -1);top:calc((.8rem - 1px) * -1);border-bottom-color:#fff}.popover.bs-popover-auto[x-placement^=bottom] .popover-header::before,.popover.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:20px;margin-left:-10px;content:"";border-bottom:1px solid #f7f7f7}.carousel,.carousel-inner,.carousel-item{position:relative}.popover.bs-popover-auto[x-placement^=left],.popover.bs-popover-left{margin-right:.8rem}.popover.bs-popover-auto[x-placement^=left] .arrow,.popover.bs-popover-left .arrow{right:0}.popover.bs-popover-auto[x-placement^=left] .arrow::after,.popover.bs-popover-auto[x-placement^=left] .arrow::before,.popover.bs-popover-left .arrow::after,.popover.bs-popover-left .arrow::before{margin-top:-.8rem;border-right-width:0}.popover.bs-popover-auto[x-placement^=left] .arrow::before,.popover.bs-popover-left .arrow::before{right:-.8rem;border-left-color:rgba(0,0,0,.25)}.popover.bs-popover-auto[x-placement^=left] .arrow::after,.popover.bs-popover-left .arrow::after{right:-webkit-calc((.8rem - 1px) * -1);right:calc((.8rem - 1px) * -1);border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:-webkit-calc(.3rem - 1px);border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:-webkit-calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel-inner{width:100%;overflow:hidden}.carousel-item{display:none;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;width:100%;-webkit-transition:-webkit-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}@supports (transform-style:preserve-3d){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}@supports (transform-style:preserve-3d){.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%)}@supports (transform-style:preserve-3d){.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-align:center;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:center center no-repeat;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-ms-flex-pack:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%}.carousel-indicators li{position:relative;-ms-flex:0 1 auto;-webkit-box-flex:0;-webkit-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;background-color:rgba(255,255,255,.5)}.carousel-indicators li::after,.carousel-indicators li::before{left:0;display:inline-block;height:10px;position:absolute;content:"";width:100%}.carousel-indicators li::before{top:-10px}.carousel-indicators li::after{bottom:-10px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.btn .fa,.btn-floating,.picker .picker__box,.picker__date-display .clockpicker-display,.product-table td,.switch label .lever,.waves-input-wrapper{vertical-align:middle}a.bg-primary:focus,a.bg-primary:hover{background-color:#0062cc!important}a.bg-secondary:focus,a.bg-secondary:hover{background-color:#6c757d!important}a.bg-success:focus,a.bg-success:hover{background-color:#1e7e34!important}a.bg-info:focus,a.bg-info:hover{background-color:#117a8b!important}a.bg-warning:focus,a.bg-warning:hover{background-color:#d39e00!important}a.bg-danger:focus,a.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover{background-color:#1d2124!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #e9ecef!important}.border-0{border:0!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-left,.rounded-top{border-top-left-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#868e96!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-circle{border-radius:50%!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:-webkit-box!important;display:-webkit-flex!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:-webkit-inline-box!important;display:-webkit-inline-flex!important;display:inline-flex!important}}.d-print-block{display:none!important}@media print{.d-print-block{display:block!important}}.d-print-inline{display:none!important}@media print{.d-print-inline{display:inline!important}}.d-print-inline-block{display:none!important}@media print{.d-print-inline-block{display:inline-block!important}.d-print-none{display:none!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;-webkit-box-orient:horizontal!important;-webkit-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;-webkit-box-orient:vertical!important;-webkit-flex-direction:column!important;flex-direction:column!important}.flex-column-reverse,.flex-row-reverse{-webkit-box-direction:reverse!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;-webkit-box-orient:horizontal!important;-webkit-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;-webkit-box-orient:vertical!important;-webkit-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;-webkit-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;-webkit-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;-webkit-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-start{-ms-flex-pack:start!important;-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;-webkit-box-pack:center!important;-webkit-justify-content:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;-webkit-justify-content:space-around!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;-webkit-box-align:start!important;-webkit-align-items:flex-start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;-webkit-box-align:end!important;-webkit-align-items:flex-end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;-webkit-box-align:center!important;-webkit-align-items:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;-webkit-align-content:flex-start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;-webkit-align-content:flex-end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;-webkit-align-content:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;-webkit-align-content:space-between!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;-webkit-align-content:space-around!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;-webkit-align-content:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;-webkit-align-self:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;-webkit-align-self:flex-start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;-webkit-align-self:flex-end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;-webkit-align-self:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;-webkit-align-self:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;-webkit-align-self:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-column,.flex-sm-row{-webkit-box-direction:normal!important}.flex-sm-row{-ms-flex-direction:row!important;-webkit-box-orient:horizontal!important;-webkit-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;-webkit-box-orient:vertical!important;-webkit-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;-webkit-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;-webkit-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;-webkit-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-sm-start{-ms-flex-pack:start!important;-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;-webkit-box-pack:center!important;-webkit-justify-content:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;-webkit-justify-content:space-around!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;-webkit-box-align:start!important;-webkit-align-items:flex-start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;-webkit-box-align:end!important;-webkit-align-items:flex-end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;-webkit-box-align:center!important;-webkit-align-items:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;-webkit-align-content:flex-start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;-webkit-align-content:flex-end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;-webkit-align-content:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;-webkit-align-content:space-between!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;-webkit-align-content:space-around!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;-webkit-align-content:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;-webkit-align-self:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;-webkit-align-self:flex-start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;-webkit-align-self:flex-end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;-webkit-align-self:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;-webkit-align-self:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;-webkit-align-self:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-column,.flex-md-row{-webkit-box-direction:normal!important}.flex-md-row{-ms-flex-direction:row!important;-webkit-box-orient:horizontal!important;-webkit-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;-webkit-box-orient:vertical!important;-webkit-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;-webkit-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;-webkit-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;-webkit-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-md-start{-ms-flex-pack:start!important;-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;-webkit-box-pack:center!important;-webkit-justify-content:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;-webkit-justify-content:space-around!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;-webkit-box-align:start!important;-webkit-align-items:flex-start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;-webkit-box-align:end!important;-webkit-align-items:flex-end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;-webkit-box-align:center!important;-webkit-align-items:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;-webkit-align-content:flex-start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;-webkit-align-content:flex-end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;-webkit-align-content:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;-webkit-align-content:space-between!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;-webkit-align-content:space-around!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;-webkit-align-content:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;-webkit-align-self:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;-webkit-align-self:flex-start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;-webkit-align-self:flex-end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;-webkit-align-self:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;-webkit-align-self:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;-webkit-align-self:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-column,.flex-lg-row{-webkit-box-direction:normal!important}.flex-lg-row{-ms-flex-direction:row!important;-webkit-box-orient:horizontal!important;-webkit-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;-webkit-box-orient:vertical!important;-webkit-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;-webkit-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;-webkit-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;-webkit-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-lg-start{-ms-flex-pack:start!important;-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;-webkit-box-pack:center!important;-webkit-justify-content:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;-webkit-justify-content:space-around!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;-webkit-box-align:start!important;-webkit-align-items:flex-start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;-webkit-box-align:end!important;-webkit-align-items:flex-end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;-webkit-box-align:center!important;-webkit-align-items:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;-webkit-align-content:flex-start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;-webkit-align-content:flex-end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;-webkit-align-content:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;-webkit-align-content:space-between!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;-webkit-align-content:space-around!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;-webkit-align-content:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;-webkit-align-self:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;-webkit-align-self:flex-start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;-webkit-align-self:flex-end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;-webkit-align-self:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;-webkit-align-self:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;-webkit-align-self:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-column,.flex-xl-row{-webkit-box-direction:normal!important}.flex-xl-row{-ms-flex-direction:row!important;-webkit-box-orient:horizontal!important;-webkit-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;-webkit-box-orient:vertical!important;-webkit-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-webkit-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;-webkit-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;-webkit-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;-webkit-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-xl-start{-ms-flex-pack:start!important;-webkit-box-pack:start!important;-webkit-justify-content:flex-start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;-webkit-box-pack:end!important;-webkit-justify-content:flex-end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;-webkit-box-pack:center!important;-webkit-justify-content:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;-webkit-box-pack:justify!important;-webkit-justify-content:space-between!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;-webkit-justify-content:space-around!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;-webkit-box-align:start!important;-webkit-align-items:flex-start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;-webkit-box-align:end!important;-webkit-align-items:flex-end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;-webkit-box-align:center!important;-webkit-align-items:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;-webkit-box-align:baseline!important;-webkit-align-items:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;-webkit-box-align:stretch!important;-webkit-align-items:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;-webkit-align-content:flex-start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;-webkit-align-content:flex-end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;-webkit-align-content:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;-webkit-align-content:space-between!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;-webkit-align-content:space-around!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;-webkit-align-content:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;-webkit-align-self:auto!important;-ms-grid-row-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;-webkit-align-self:flex-start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;-webkit-align-self:flex-end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;-webkit-align-self:center!important;-ms-grid-row-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;-webkit-align-self:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;-webkit-align-self:stretch!important;-ms-grid-row-align:stretch!important;align-self:stretch!important}}.divider-new,.navbar .nav-flex-icons,.navbar.double-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal}.error404,.stepper-vertical,.stepper-vertical li,.stepper-vertical li a .label{-webkit-box-orient:vertical;-webkit-box-direction:normal}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-bottom,.fixed-top{position:fixed;right:0;left:0;z-index:1030}.fixed-top{top:0}.fixed-bottom{bottom:0}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.btn .fa,.card .card-body{position:relative}.sr-only{white-space:nowrap;-webkit-clip-path:inset(50%);clip-path:inset(50%)}.sr-only-focusable:active,.sr-only-focusable:focus{white-space:normal;-webkit-clip-path:none;clip-path:none}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-1{margin:.25rem!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.btn,.classic-tabs li a,.font-up,footer.page-footer .title{text-transform:uppercase}.font-weight-light{font-weight:300!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0062cc!important}.text-secondary{color:#868e96!important}a.text-secondary:focus,a.text-secondary:hover{color:#6c757d!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#1e7e34!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#117a8b!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#d39e00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#bd2130!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#dae0e5!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#1d2124!important}.text-muted{color:#868e96!important}.text-hide{font:0/0 a;color:transparent;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.mdb-color.lighten-5{background-color:#D0D6E2!important}.mdb-color.lighten-4{background-color:#B1BACE!important}.mdb-color.lighten-3{background-color:#929FBA!important}.mdb-color.lighten-2{background-color:#7283A7!important}.mdb-color.lighten-1{background-color:#59698D!important}.mdb-color-text{color:#45526E!important}.mdb-color.darken-1{background-color:#3B465E!important}.mdb-color.darken-2{background-color:#2E3951!important}.mdb-color.darken-3{background-color:#1C2A48!important}.mdb-color.darken-4{background-color:#1C2331!important}.red.lighten-5{background-color:#FFEBEE!important}.red.lighten-4{background-color:#FFCDD2!important}.red.lighten-3{background-color:#EF9A9A!important}.red.lighten-2{background-color:#E57373!important}.red.lighten-1{background-color:#EF5350!important}.red{background-color:#F44336!important}.red-text{color:#F44336!important}.red.darken-1{background-color:#E53935!important}.red.darken-2{background-color:#D32F2F!important}.red.darken-3{background-color:#C62828!important}.red.darken-4{background-color:#B71C1C!important}.red.accent-1{background-color:#FF8A80!important}.red.accent-2{background-color:#FF5252!important}.red.accent-3{background-color:#FF1744!important}.red.accent-4{background-color:#D50000!important}.pink.lighten-5{background-color:#fce4ec!important}.pink.lighten-4{background-color:#f8bbd0!important}.pink.lighten-3{background-color:#f48fb1!important}.pink.lighten-2{background-color:#f06292!important}.pink.lighten-1{background-color:#ec407a!important}.pink{background-color:#e91e63!important}.pink-text{color:#e91e63!important}.pink.darken-1{background-color:#d81b60!important}.pink.darken-2{background-color:#c2185b!important}.pink.darken-3{background-color:#ad1457!important}.pink.darken-4{background-color:#880e4f!important}.pink.accent-1{background-color:#ff80ab!important}.pink.accent-2{background-color:#ff4081!important}.pink.accent-3{background-color:#f50057!important}.pink.accent-4{background-color:#c51162!important}.purple.lighten-5{background-color:#f3e5f5!important}.purple.lighten-4{background-color:#e1bee7!important}.purple.lighten-3{background-color:#ce93d8!important}.purple.lighten-2{background-color:#ba68c8!important}.purple.lighten-1{background-color:#ab47bc!important}.purple{background-color:#9c27b0!important}.purple-text{color:#9c27b0!important}.purple.darken-1{background-color:#8e24aa!important}.purple.darken-2{background-color:#7b1fa2!important}.purple.darken-3{background-color:#6a1b9a!important}.purple.darken-4{background-color:#4a148c!important}.purple.accent-1{background-color:#ea80fc!important}.purple.accent-2{background-color:#e040fb!important}.purple.accent-3{background-color:#d500f9!important}.purple.accent-4{background-color:#a0f!important}.deep-purple.lighten-5{background-color:#ede7f6!important}.deep-purple.lighten-4{background-color:#d1c4e9!important}.deep-purple.lighten-3{background-color:#b39ddb!important}.deep-purple.lighten-2{background-color:#9575cd!important}.deep-purple.lighten-1{background-color:#7e57c2!important}.deep-purple{background-color:#673ab7!important}.deep-purple-text{color:#673ab7!important}.deep-purple.darken-1{background-color:#5e35b1!important}.deep-purple.darken-2{background-color:#512da8!important}.deep-purple.darken-3{background-color:#4527a0!important}.deep-purple.darken-4{background-color:#311b92!important}.deep-purple.accent-1{background-color:#b388ff!important}.deep-purple.accent-2{background-color:#7c4dff!important}.deep-purple.accent-3{background-color:#651fff!important}.deep-purple.accent-4{background-color:#6200ea!important}.indigo.lighten-5{background-color:#e8eaf6!important}.indigo.lighten-4{background-color:#c5cae9!important}.indigo.lighten-3{background-color:#9fa8da!important}.indigo.lighten-2{background-color:#7986cb!important}.indigo.lighten-1{background-color:#5c6bc0!important}.indigo{background-color:#3f51b5!important}.indigo-text{color:#3f51b5!important}.indigo.darken-1{background-color:#3949ab!important}.indigo.darken-2{background-color:#303f9f!important}.indigo.darken-3{background-color:#283593!important}.indigo.darken-4{background-color:#1a237e!important}.indigo.accent-1{background-color:#8c9eff!important}.indigo.accent-2{background-color:#536dfe!important}.indigo.accent-3{background-color:#3d5afe!important}.indigo.accent-4{background-color:#304ffe!important}.blue.lighten-5{background-color:#E3F2FD!important}.blue.lighten-4{background-color:#BBDEFB!important}.blue.lighten-3{background-color:#90CAF9!important}.blue.lighten-2{background-color:#64B5F6!important}.blue.lighten-1{background-color:#42A5F5!important}.blue{background-color:#2196F3!important}.blue-text{color:#2196F3!important}.blue.darken-1{background-color:#1E88E5!important}.blue.darken-2{background-color:#1976D2!important}.blue.darken-3{background-color:#1565C0!important}.blue.darken-4{background-color:#0D47A1!important}.blue.accent-1{background-color:#82B1FF!important}.blue.accent-2{background-color:#448AFF!important}.blue.accent-3{background-color:#2979FF!important}.blue.accent-4{background-color:#2962FF!important}.light-blue.lighten-5{background-color:#e1f5fe!important}.light-blue.lighten-4{background-color:#b3e5fc!important}.light-blue.lighten-3{background-color:#81d4fa!important}.light-blue.lighten-2{background-color:#4fc3f7!important}.light-blue.lighten-1{background-color:#29b6f6!important}.light-blue{background-color:#03a9f4!important}.light-blue.darken-1{background-color:#039be5!important}.light-blue.darken-2{background-color:#0288d1!important}.light-blue.darken-3{background-color:#0277bd!important}.light-blue.darken-4{background-color:#01579b!important}.light-blue.accent-1{background-color:#80d8ff!important}.light-blue.accent-2{background-color:#40c4ff!important}.light-blue.accent-3{background-color:#00b0ff!important}.light-blue.accent-4{background-color:#0091ea!important}.cyan.lighten-5{background-color:#e0f7fa!important}.cyan.lighten-4{background-color:#b2ebf2!important}.cyan.lighten-3{background-color:#80deea!important}.cyan.lighten-2{background-color:#4dd0e1!important}.cyan.lighten-1{background-color:#26c6da!important}.cyan{background-color:#00bcd4!important}.cyan-text{color:#00bcd4!important}.cyan.darken-1{background-color:#00acc1!important}.cyan.darken-2{background-color:#0097a7!important}.cyan.darken-3{background-color:#00838f!important}.cyan.darken-4{background-color:#006064!important}.cyan.accent-1{background-color:#84ffff!important}.cyan.accent-2{background-color:#18ffff!important}.cyan.accent-3{background-color:#00e5ff!important}.cyan.accent-4{background-color:#00b8d4!important}.teal.lighten-5{background-color:#e0f2f1!important}.teal.lighten-4{background-color:#b2dfdb!important}.teal.lighten-3{background-color:#80cbc4!important}.teal.lighten-2{background-color:#4db6ac!important}.teal.lighten-1{background-color:#26a69a!important}.teal{background-color:#009688!important}.teal-text{color:#009688!important}.teal.darken-1{background-color:#00897b!important}.teal.darken-2{background-color:#00796b!important}.teal.darken-3{background-color:#00695c!important}.teal.darken-4{background-color:#004d40!important}.teal.accent-1{background-color:#a7ffeb!important}.teal.accent-2{background-color:#64ffda!important}.teal.accent-3{background-color:#1de9b6!important}.teal.accent-4{background-color:#00bfa5!important}.green.lighten-5{background-color:#E8F5E9!important}.green.lighten-4{background-color:#C8E6C9!important}.green.lighten-3{background-color:#A5D6A7!important}.green.lighten-2{background-color:#81C784!important}.green.lighten-1{background-color:#66BB6A!important}.green{background-color:#4CAF50!important}.green-text{color:#4CAF50!important}.green.darken-1{background-color:#43A047!important}.green.darken-2{background-color:#388E3C!important}.green.darken-3{background-color:#2E7D32!important}.green.darken-4{background-color:#1B5E20!important}.green.accent-1{background-color:#B9F6CA!important}.green.accent-2{background-color:#69F0AE!important}.green.accent-3{background-color:#00E676!important}.green.accent-4{background-color:#00C853!important}.light-green.lighten-5{background-color:#f1f8e9!important}.light-green.lighten-4{background-color:#dcedc8!important}.light-green.lighten-3{background-color:#c5e1a5!important}.light-green.lighten-2{background-color:#aed581!important}.light-green.lighten-1{background-color:#9ccc65!important}.light-green{background-color:#8bc34a!important}.light-green-text{color:#8bc34a!important}.light-green.darken-1{background-color:#7cb342!important}.light-green.darken-2{background-color:#689f38!important}.light-green.darken-3{background-color:#558b2f!important}.light-green.darken-4{background-color:#33691e!important}.light-green.accent-1{background-color:#ccff90!important}.light-green.accent-2{background-color:#b2ff59!important}.light-green.accent-3{background-color:#76ff03!important}.light-green.accent-4{background-color:#64dd17!important}.lime.lighten-5{background-color:#f9fbe7!important}.lime.lighten-4{background-color:#f0f4c3!important}.lime.lighten-3{background-color:#e6ee9c!important}.lime.lighten-2{background-color:#dce775!important}.lime.lighten-1{background-color:#d4e157!important}.lime{background-color:#cddc39!important}.lime-text{color:#cddc39!important}.lime.darken-1{background-color:#c0ca33!important}.lime.darken-2{background-color:#afb42b!important}.lime.darken-3{background-color:#9e9d24!important}.lime.darken-4{background-color:#827717!important}.lime.accent-1{background-color:#f4ff81!important}.lime.accent-2{background-color:#eeff41!important}.lime.accent-3{background-color:#c6ff00!important}.lime.accent-4{background-color:#aeea00!important}.yellow.lighten-5{background-color:#fffde7!important}.yellow.lighten-4{background-color:#fff9c4!important}.yellow.lighten-3{background-color:#fff59d!important}.yellow.lighten-2{background-color:#fff176!important}.yellow.lighten-1{background-color:#ffee58!important}.yellow{background-color:#ffeb3b!important}.yellow-text{color:#ffeb3b!important}.yellow.darken-1{background-color:#fdd835!important}.yellow.darken-2{background-color:#fbc02d!important}.yellow.darken-3{background-color:#f9a825!important}.yellow.darken-4{background-color:#f57f17!important}.yellow.accent-1{background-color:#ffff8d!important}.yellow.accent-2{background-color:#ff0!important}.yellow.accent-3{background-color:#ffea00!important}.yellow.accent-4{background-color:#ffd600!important}.amber.lighten-5{background-color:#fff8e1!important}.amber.lighten-4{background-color:#ffecb3!important}.amber.lighten-3{background-color:#ffe082!important}.amber.lighten-2{background-color:#ffd54f!important}.amber.lighten-1{background-color:#ffca28!important}.amber{background-color:#ffc107!important}.amber-text{color:#ffc107!important}.amber.darken-1{background-color:#ffb300!important}.amber.darken-2{background-color:#ffa000!important}.amber.darken-3{background-color:#ff8f00!important}.amber.darken-4{background-color:#ff6f00!important}.amber.accent-1{background-color:#ffe57f!important}.amber.accent-2{background-color:#ffd740!important}.amber.accent-3{background-color:#ffc400!important}.amber.accent-4{background-color:#ffab00!important}.orange.lighten-5{background-color:#fff3e0!important}.orange.lighten-4{background-color:#ffe0b2!important}.orange.lighten-3{background-color:#ffcc80!important}.orange.lighten-2{background-color:#ffb74d!important}.orange.lighten-1{background-color:#ffa726!important}.orange{background-color:#ff9800!important}.orange-text{color:#ff9800!important}.orange.darken-1{background-color:#fb8c00!important}.orange.darken-2{background-color:#f57c00!important}.orange.darken-3{background-color:#ef6c00!important}.orange.darken-4{background-color:#e65100!important}.orange.accent-1{background-color:#ffd180!important}.orange.accent-2{background-color:#ffab40!important}.orange.accent-3{background-color:#ff9100!important}.orange.accent-4{background-color:#ff6d00!important}.deep-orange.lighten-5{background-color:#fbe9e7!important}.deep-orange.lighten-4{background-color:#ffccbc!important}.deep-orange.lighten-3{background-color:#ffab91!important}.deep-orange.lighten-2{background-color:#ff8a65!important}.deep-orange.lighten-1{background-color:#ff7043!important}.deep-orange{background-color:#ff5722!important}.deep-orange-text{color:#ff5722!important}.deep-orange.darken-1{background-color:#f4511e!important}.deep-orange.darken-2{background-color:#e64a19!important}.deep-orange.darken-3{background-color:#d84315!important}.deep-orange.darken-4{background-color:#bf360c!important}.deep-orange.accent-1{background-color:#ff9e80!important}.deep-orange.accent-2{background-color:#ff6e40!important}.deep-orange.accent-3{background-color:#ff3d00!important}.deep-orange.accent-4{background-color:#dd2c00!important}.brown.lighten-5{background-color:#efebe9!important}.brown.lighten-4{background-color:#d7ccc8!important}.brown.lighten-3{background-color:#bcaaa4!important}.brown.lighten-2{background-color:#a1887f!important}.brown.lighten-1{background-color:#8d6e63!important}.brown{background-color:#795548!important}.brown-text{color:#795548!important}.brown.darken-1{background-color:#6d4c41!important}.brown.darken-2{background-color:#5d4037!important}.brown.darken-3{background-color:#4e342e!important}.brown.darken-4{background-color:#3e2723!important}.blue-grey.lighten-5{background-color:#eceff1!important}.blue-grey.lighten-4{background-color:#cfd8dc!important}.blue-grey.lighten-3{background-color:#b0bec5!important}.blue-grey.lighten-2{background-color:#90a4ae!important}.blue-grey.lighten-1{background-color:#78909c!important}.blue-grey{background-color:#607d8b!important}.blue-grey-text{color:#607d8b!important}.blue-grey.darken-1{background-color:#546e7a!important}.blue-grey.darken-2{background-color:#455a64!important}.blue-grey.darken-3{background-color:#37474f!important}.blue-grey.darken-4{background-color:#263238!important}.grey.lighten-5{background-color:#fafafa!important}.grey.lighten-4{background-color:#f5f5f5!important}.grey.lighten-3{background-color:#eee!important}.grey.lighten-2{background-color:#e0e0e0!important}.grey.lighten-1{background-color:#bdbdbd!important}.grey{background-color:#9e9e9e!important}.grey-text{color:#9e9e9e!important}.grey.darken-1{background-color:#757575!important}.grey.darken-2{background-color:#616161!important}.grey.darken-3{background-color:#424242!important}.grey.darken-4{background-color:#212121!important}.card .shades.card-review,.shades.black,.shades.picker__list-item:hover{background-color:#000!important}.card .shades.card-reveal,.card-wrapper .shades.face,.carousel-thumbnails .carousel-indicators .shades.active,.picker__box .picker__header .shades.picker__select--month.browser-default,.picker__box .picker__header .shades.picker__select--year.browser-default,.shades.picker__list-item,.shades.white,.testimonial-card .shades.avatar{background-color:#FFF!important}.shades.transparent{background-color:transparent!important}.black,.card .card-review,.picker__list-item:hover{background-color:#000!important}.black-text,.btn-link,.card .activator,.card-wrapper .face .content .rotate-btn,.toast-close-button:focus,.toast-close-button:hover{color:#000!important}.card .card-reveal,.card-wrapper .face,.carousel-thumbnails .carousel-indicators .active,.picker__box .picker__header .picker__select--month.browser-default,.picker__box .picker__header .picker__select--year.browser-default,.picker__list-item,.testimonial-card .avatar,.white{background-color:#FFF!important}#toast-container>div,.btn,.card.card-cascade .view.gradient-card-header,.card.card-dark .activator,.card.card-dark .card-body,.card.card-dark .card-body a,.clockpicker-display .clockpicker-display-column #click-am.text-primary,.clockpicker-display .clockpicker-display-column #click-pm.text-primary,.clockpicker-display .clockpicker-display-column .clockpicker-span-hours.text-primary,.clockpicker-display .clockpicker-display-column .clockpicker-span-minutes.text-primary,.colorful-side-nav .collapsible a,.colorful-side-nav .social a,.colorful-side-nav p,.dark-side-nav .collapsible a,.dark-side-nav .social a,.dark-side-nav p,.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-tick,.darktheme .picker__box .picker__date-display .clockpicker-display,.darktheme .picker__box .picker__date-display .clockpicker-display .clockpicker-span-am-pm,.darktheme .picker__box .picker__footer button,.dropdown .dropdown-menu .dropdown-item:active,.dropdown .dropdown-menu .dropdown-item:hover,.picker--focused .picker__list-item--selected,.picker--time .picker__button--clear:focus,.picker--time .picker__button--clear:focus:before,.picker--time .picker__button--clear:hover,.picker--time .picker__button--clear:hover:before,.picker__box .picker__header .picker__date-display,.picker__box .picker__table .picker--focused,.picker__box .picker__table .picker__day--outfocus,.picker__box .picker__table .picker__day--selected,.picker__box .picker__table .picker__day--selected:hover,.picker__date-display,.picker__date-display .clockpicker-display .clockpicker-display-column #click-am.text-primary,.picker__date-display .clockpicker-display .clockpicker-display-column #click-pm.text-primary,.picker__date-display .clockpicker-display .clockpicker-display-column .clockpicker-span-hours.text-primary,.picker__date-display .clockpicker-display .clockpicker-display-column .clockpicker-span-minutes.text-primary,.picker__list-item--selected,.picker__list-item--selected:hover,.side-nav,.side-nav .search-form .form-control,.stylish-side-nav .collapsible a,.stylish-side-nav .social a,.stylish-side-nav p,.toast-close-button,.toast-message a,.toast-message label,.white-text,section .contact{color:#FFF!important}.transparent{background-color:transparent!important}.transparent-text{color:transparent!important}.light-blue-text{color:#82B1FF!important}.dark-grey-text{color:#4f4f4f!important}.danger-color,.stepper li.warning a .circle,.toast-error{background-color:#ff3547!important}.danger-color-dark{background-color:#C00!important}.toast-warning,.warning-color{background-color:#fb3!important}.warning-color-dark{background-color:#F80!important}.success-color,.toast-success{background-color:#00C851!important}.success-color-dark{background-color:#007E33!important}.info-color,.toast-info{background-color:#33b5e5!important}.info-color-dark{background-color:#09C!important}.default-color{background-color:#2BBBAD!important}.default-color-dark{background-color:#00695c!important}.primary-color,.stepper li.active a .circle,.stepper li.completed a .circle{background-color:#4285F4!important}.primary-color-dark{background-color:#0d47a1!important}.secondary-color{background-color:#a6c!important}.secondary-color-dark{background-color:#93C!important}.elegant-color{background-color:#2E2E2E!important}.elegant-color-dark{background-color:#212121!important}.stylish-color{background-color:#4B515D!important}.stylish-color-dark{background-color:#3E4551!important}.special-color{background-color:#37474F!important}.special-color-dark{background-color:#263238!important}.unique-color{background-color:#3F729B!important}.unique-color-dark{background-color:#1C2331!important}.mdb-color{background-color:#45526E!important}.rgba-blue-light{background-color:rgba(3,169,244,.3)!important}.rgba-red-light{background-color:rgba(244,67,54,.3)!important}.rgba-pink-light{background-color:rgba(233,30,99,.3)!important}.rgba-purple-light{background-color:rgba(156,39,176,.3)!important}.rgba-indigo-light{background-color:rgba(63,81,181,.3)!important}.rgba-cyan-light{background-color:rgba(0,188,212,.3)!important}.rgba-teal-light{background-color:rgba(0,150,136,.3)!important}.rgba-green-light{background-color:rgba(76,175,80,.3)!important}.rgba-lime-light{background-color:rgba(205,220,57,.3)!important}.rgba-yellow-light{background-color:rgba(255,235,59,.3)!important}.rgba-orange-light{background-color:rgba(255,152,0,.3)!important}.rgba-brown-light{background-color:rgba(121,85,72,.3)!important}.rgba-grey-light{background-color:rgba(158,158,158,.3)!important}.rgba-bluegrey-light{background-color:rgba(96,125,139,.3)!important}.rgba-black-light{background-color:rgba(0,0,0,.3)!important}.rgba-stylish-light{background-color:rgba(62,69,81,.3)!important}.rgba-white-light{background-color:rgba(255,255,255,.3)!important}.rgba-blue-strong{background-color:rgba(3,169,244,.7)!important}.rgba-red-strong{background-color:rgba(244,67,54,.7)!important}.rgba-pink-strong{background-color:rgba(233,30,99,.7)!important}.rgba-purple-strong{background-color:rgba(156,39,176,.7)!important}.rgba-indigo-strong{background-color:rgba(63,81,181,.7)!important}.rgba-cyan-strong{background-color:rgba(0,188,212,.7)!important}.rgba-teal-strong{background-color:rgba(0,150,136,.7)!important}.rgba-green-strong{background-color:rgba(76,175,80,.7)!important}.rgba-lime-strong{background-color:rgba(205,220,57,.7)!important}.rgba-yellow-strong{background-color:rgba(255,235,59,.7)!important}.rgba-orange-strong{background-color:rgba(255,152,0,.7)!important}.rgba-brown-strong{background-color:rgba(121,85,72,.7)!important}.rgba-grey-strong{background-color:rgba(158,158,158,.7)!important}.rgba-bluegrey-strong{background-color:rgba(96,125,139,.7)!important}.rgba-black-strong{background-color:rgba(0,0,0,.7)!important}.rgba-stylish-strong{background-color:rgba(62,69,81,.7)!important}.rgba-white-strong{background-color:rgba(255,255,255,.7)!important}.rgba-blue-slight{background-color:rgba(3,169,244,.1)!important}.rgba-red-slight{background-color:rgba(244,67,54,.1)!important}.rgba-pink-slight{background-color:rgba(233,30,99,.1)!important}.rgba-purple-slight{background-color:rgba(156,39,176,.1)!important}.rgba-indigo-slight{background-color:rgba(63,81,181,.1)!important}.rgba-cyan-slight{background-color:rgba(0,188,212,.1)!important}.rgba-teal-slight{background-color:rgba(0,150,136,.1)!important}.rgba-green-slight{background-color:rgba(76,175,80,.1)!important}.rgba-lime-slight{background-color:rgba(205,220,57,.1)!important}.rgba-yellow-slight{background-color:rgba(255,235,59,.1)!important}.rgba-orange-slight{background-color:rgba(255,152,0,.1)!important}.rgba-brown-slight{background-color:rgba(121,85,72,.1)!important}.rgba-grey-slight{background-color:rgba(158,158,158,.1)!important}.rgba-bluegrey-slight{background-color:rgba(96,125,139,.1)!important}.rgba-black-slight{background-color:rgba(0,0,0,.1)!important}.rgba-stylish-slight{background-color:rgba(62,69,81,.1)!important}.rgba-white-slight{background-color:rgba(255,255,255,.1)!important}.bg-primary{background-color:#4285F4!important}.bg-danger{background-color:#ff3547!important}.bg-warning{background-color:#F80!important}.bg-success{background-color:#00C851!important}.bg-info{background-color:#33b5e5!important}.bg-default{background-color:#2BBBAD!important}.bg-secondary{background-color:#a6c!important}.bg-elegant{background-color:#2E2E2E!important}.bg-unique{background-color:#880e4f!important}.bg-dark-green{background-color:#388E3C!important}.bg-mdb-color{background-color:#59698D!important}.bg-red{background-color:#D32F2F!important}.bg-pink{background-color:#ec407a!important}.bg-purple{background-color:#8e24aa!important}.bg-deep-purple{background-color:#512da8!important}.bg-indigo{background-color:#3f51b5!important}.bg-blue{background-color:#1976D2!important}.bg-light-blue{background-color:#82B1FF!important}.bg-cyan{background-color:#00bcd4!important}.bg-teal{background-color:#00796b!important}.bg-green{background-color:#388E3C!important}.bg-light-green{background-color:#8bc34a!important}.bg-lime{background-color:#afb42b!important}.bg-yellow{background-color:#fbc02d!important}.bg-amber{background-color:#ffa000!important}.bg-orange{background-color:#f57c00!important}.bg-deep-orange{background-color:#ff7043!important}.bg-brown{background-color:#795548!important}.bg-grey{background-color:#616161!important}.bg-blue-grey{background-color:#78909c!important}.bg-white{background-color:#fff!important}.bg-black{background-color:#000!important}.card.card-cascade.wider,.colorful-select .dropdown-content li.disabled a:hover,.colorful-select .dropdown-content li.disabled span:hover,.colorful-select .dropdown-content li.disabled.active span,.colorful-select .dropdown-content li.optgroup a:hover,.colorful-select .dropdown-content li.optgroup span:hover,.colorful-select .dropdown-content li.optgroup.active span,.colorful-select .dropdown-content li:disabled a:hover,.colorful-select .dropdown-content li:disabled span:hover,.colorful-select .dropdown-content li:disabled.active span,.modal-dialog.cascading-modal.modal-avatar .modal-header,.z-depth-0{-webkit-box-shadow:none!important;box-shadow:none!important}#toast-container>div,.author-box,.badge,.btn,.btn-primary.active:not([disabled]):not(.disabled),.btn-primary:not([disabled]):not(.disabled):active,.card-wrapper .back,.card-wrapper .front,.card.card-cascade.wider .card-body,.card:not([class*=card-outline-]),.chip,.counter,.dropdown-content,.jumbotron,.md-pills .nav-link.active,.modal-dialog.cascading-modal .modal-c-tabs .nav-tabs,.modal-dialog.modal-notify .modal-header,.navbar,.pagination .active .page-link,.pricing-card .price .version,.section-blog-fw .view,.show>.btn-primary.dropdown-toggle,.side-nav,.social-list,.z-depth-1{-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12)}.btn-floating,.btn-floating.btn-flat.active,.btn:active,.btn:focus,.btn:hover,.card.card-cascade.card-avatar img,.card.card-cascade.wider.reverse .card-body,.colorful-select .dropdown-content li.active span,.comments-list .badge,.dropdown .dropdown-menu .dropdown-item:active,.dropdown .dropdown-menu .dropdown-item:hover,.form-header,.md-pills .nav-link.active:hover,.media .media-left img,.modal-dialog .modal-content,.modal-dialog.cascading-modal .modal-header,.nav-tabs,.picker__box .picker__table .picker--focused,.picker__box .picker__table .picker__day--selected,.picker__box .picker__table .picker__day--selected:hover,.pricing-card .header,.reply-form .badge,.z-depth-1-half,ul.instagram-photos li img{-webkit-box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15)}.btn-floating:hover,.card-overlay,.card.card-cascade .view,.colorful-select .dropdown-content li a:hover,.colorful-select .dropdown-content li span:hover,.comments-list img,.modal-dialog.cascading-modal.modal-avatar .modal-header img,.reply-form img,.testimonial-carousel .testimonial .avatar img,.z-depth-2{-webkit-box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.z-depth-3{-webkit-box-shadow:0 12px 15px 0 rgba(0,0,0,.24),0 17px 50px 0 rgba(0,0,0,.19);box-shadow:0 12px 15px 0 rgba(0,0,0,.24),0 17px 50px 0 rgba(0,0,0,.19)}.z-depth-4{-webkit-box-shadow:0 16px 28px 0 rgba(0,0,0,.22),0 25px 55px 0 rgba(0,0,0,.21);box-shadow:0 16px 28px 0 rgba(0,0,0,.22),0 25px 55px 0 rgba(0,0,0,.21)}.z-depth-5{-webkit-box-shadow:0 27px 24px 0 rgba(0,0,0,.2),0 40px 77px 0 rgba(0,0,0,.22);box-shadow:0 27px 24px 0 rgba(0,0,0,.2),0 40px 77px 0 rgba(0,0,0,.22)}.hoverable{-webkit-transition:box-shadow .55s;-webkit-transition:-webkit-box-shadow .55s;transition:-webkit-box-shadow .55s;transition:box-shadow .55s;transition:box-shadow .55s,-webkit-box-shadow .55s;-webkit-box-shadow:0;box-shadow:0}.hoverable:hover{-webkit-transition:box-shadow .45s;-webkit-transition:-webkit-box-shadow .45s;transition:-webkit-box-shadow .45s;transition:box-shadow .45s;transition:box-shadow .45s,-webkit-box-shadow .45s;-webkit-box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}a{color:#0275d8;text-decoration:none;cursor:pointer}a:focus,a:hover{text-decoration:none}a:not([href]):not([tabindex]),a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}.disabled{cursor:not-allowed!important}.author-box,.badge,.jumbotron,.list-group .list-group-item,.navbar-toggler{border-radius:2px}.card .card-circle ul,.card-overlay ul,.flex-center ul,.section.team-section .avatar ul,.testimonial-carousel .testimonial .avatar ul{list-style-type:none;padding:0;text-align:center}.pr-0,.px-0{padding-right:0!important}.pl-0,.px-0{padding-left:0!important}.pt-0,.py-0{padding-top:0!important}.pb-0,.py-0{padding-bottom:0!important}.media .avatar-sm{width:56px;border-radius:50%}.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounce{20%,53%,80%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{20%,53%,80%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;-ms-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{50%,from,to{opacity:1}25%,75%{opacity:0}}@keyframes flash{50%,from,to{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{from,to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}}@keyframes pulse{from,to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{from,to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}}@keyframes rubberBand{from,to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{from,to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{from,to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes headShake{0%{-webkit-transform:translateX(0);transform:translateX(0)}6.5%{-webkit-transform:translateX(-6px) rotateY(-9deg);transform:translateX(-6px) rotateY(-9deg)}18.5%{-webkit-transform:translateX(5px) rotateY(7deg);transform:translateX(5px) rotateY(7deg)}31.5%{-webkit-transform:translateX(-3px) rotateY(-5deg);transform:translateX(-3px) rotateY(-5deg)}43.5%{-webkit-transform:translateX(2px) rotateY(3deg);transform:translateX(2px) rotateY(3deg)}50%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes headShake{0%{-webkit-transform:translateX(0);transform:translateX(0)}6.5%{-webkit-transform:translateX(-6px) rotateY(-9deg);transform:translateX(-6px) rotateY(-9deg)}18.5%{-webkit-transform:translateX(5px) rotateY(7deg);transform:translateX(5px) rotateY(7deg)}31.5%{-webkit-transform:translateX(-3px) rotateY(-5deg);transform:translateX(-3px) rotateY(-5deg)}43.5%{-webkit-transform:translateX(2px) rotateY(3deg);transform:translateX(2px) rotateY(3deg)}50%{-webkit-transform:translateX(0);transform:translateX(0)}}.headShake{-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-name:headShake;animation-name:headShake}@-webkit-keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}to{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}@keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}to{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}.swing{-webkit-transform-origin:top center;-ms-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{from,to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}}@keyframes tada{from,to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{from,to{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}}@keyframes wobble{from,to{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes jello{11.1%,from,to{-webkit-transform:none;transform:none}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-.78125deg) skewY(-.78125deg);transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{-webkit-transform:skewX(.39063deg) skewY(.39063deg);transform:skewX(.39063deg) skewY(.39063deg)}88.8%{-webkit-transform:skewX(-.19531deg) skewY(-.19531deg);transform:skewX(-.19531deg) skewY(-.19531deg)}}@keyframes jello{11.1%,from,to{-webkit-transform:none;transform:none}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-.78125deg) skewY(-.78125deg);transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{-webkit-transform:skewX(.39063deg) skewY(.39063deg);transform:skewX(.39063deg) skewY(.39063deg)}88.8%{-webkit-transform:skewX(-.19531deg) skewY(-.19531deg);transform:skewX(-.19531deg) skewY(-.19531deg)}}.jello{-webkit-animation-name:jello;animation-name:jello;-webkit-transform-origin:center;-ms-transform-origin:center;transform-origin:center}@-webkit-keyframes bounceIn{20%,40%,60%,80%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes bounceIn{20%,40%,60%,80%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceInDown{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}to{-webkit-transform:none;transform:none}}@keyframes bounceInDown{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}to{-webkit-transform:none;transform:none}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}to{-webkit-transform:none;transform:none}}@keyframes bounceInLeft{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}to{-webkit-transform:none;transform:none}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}from{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}to{-webkit-transform:none;transform:none}}@keyframes bounceInRight{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}from{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}to{-webkit-transform:none;transform:none}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}from{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes bounceInUp{60%,75%,90%,from,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}from{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}to{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}to{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{from{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDownBig{from{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{from{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeft{from{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{from{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeftBig{from{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{from{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRight{from{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{from{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRightBig{from{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{from{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUp{from{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{from{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUpBig{from{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}to{opacity:1;-webkit-transform:none;transform:none}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{from{opacity:1}to{opacity:0}}@keyframes fadeOut{from{opacity:1}to{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{from{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}to{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{from{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}to{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{from{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{from{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}.flipInY,.flipOutX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipInY{from{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{from{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{from{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}to{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@keyframes flipOutX{from{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}to{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX}@-webkit-keyframes flipOutY{from{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}to{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@keyframes flipOutY{from{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}to{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY}@-webkit-keyframes lightSpeedIn{from{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}to{-webkit-transform:none;transform:none;opacity:1}}@keyframes lightSpeedIn{from{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}to{-webkit-transform:none;transform:none;opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{from{opacity:1}to{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}@keyframes lightSpeedOut{from{opacity:1}to{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{from{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}to{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateIn{from{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}to{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{from{-webkit-transform-origin:center;transform-origin:center;opacity:1}to{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}@keyframes rotateOut{from{-webkit-transform-origin:center;transform-origin:center;opacity:1}to{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}@keyframes rotateOutDownLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutDownRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutUpLeft{from{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}to{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}@keyframes rotateOutUpRight{from{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}to{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}to{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}@keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}to{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{from{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes rollIn{from{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}to{opacity:1;-webkit-transform:none;transform:none}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}@keyframes rollOut{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{from{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{from{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInDown{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInLeft{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInRight{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInUp{from{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{from{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}@keyframes zoomOut{from{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}@-webkit-keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{from{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInLeft{from{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{from{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInRight{from{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes slideOutLeft{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes slideOutRight{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}.m-0{margin:0!important}.mr-1,.mx-1{margin-right:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.m-1,.section-blog-fw .author-box,.section-blog-fw .jumbotron{margin:.25rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.m-2{margin:.5rem!important}.mr-3,.mx-3{margin-right:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.m-3{margin:1rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.m-4{margin:1.5rem!important}.mr-5,.mx-5{margin-right:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.m-5{margin:3rem!important}.mr-auto,.mx-auto{margin-right:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.p-0{padding:0!important}.pr-1,.px-1{padding-right:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.p-1{padding:.25rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.p-2{padding:.5rem!important}.pr-3,.px-3{padding-right:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.p-3{padding:1rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.p-4{padding:1.5rem!important}.pr-5,.px-5{padding-right:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.p-5{padding:3rem!important}.m-auto{margin:auto!important}@media (min-width:576px){.mr-sm-0,.mx-sm-0{margin-right:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.m-sm-0{margin:0!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.m-sm-1{margin:.25rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.m-sm-2{margin:.5rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.m-sm-3{margin:1rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.m-sm-4{margin:1.5rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.m-sm-5{margin:3rem!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.p-sm-0{padding:0!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.p-sm-1{padding:.25rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.p-sm-2{padding:.5rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.p-sm-3{padding:1rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.p-sm-4{padding:1.5rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.p-sm-5{padding:3rem!important}.m-sm-auto{margin:auto!important}}@media (min-width:768px){.mr-md-0,.mx-md-0{margin-right:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.m-md-0{margin:0!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.m-md-1{margin:.25rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.m-md-2{margin:.5rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.m-md-3{margin:1rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.m-md-4{margin:1.5rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.m-md-5{margin:3rem!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.p-md-0{padding:0!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.p-md-1{padding:.25rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.p-md-2{padding:.5rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.p-md-3{padding:1rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.p-md-4{padding:1.5rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.p-md-5{padding:3rem!important}.m-md-auto{margin:auto!important}}@media (min-width:992px){.mr-lg-0,.mx-lg-0{margin-right:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.m-lg-0{margin:0!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.m-lg-1{margin:.25rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.m-lg-2{margin:.5rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.m-lg-3{margin:1rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.m-lg-4{margin:1.5rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.m-lg-5{margin:3rem!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.p-lg-0{padding:0!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.p-lg-1{padding:.25rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.p-lg-2{padding:.5rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.p-lg-3{padding:1rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.p-lg-4{padding:1.5rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.p-lg-5{padding:3rem!important}.m-lg-auto{margin:auto!important}}@media (min-width:1200px){.mr-xl-0,.mx-xl-0{margin-right:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.m-xl-0{margin:0!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.m-xl-1{margin:.25rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.m-xl-2{margin:.5rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.m-xl-3{margin:1rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.m-xl-4{margin:1.5rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.m-xl-5{margin:3rem!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.p-xl-0{padding:0!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.p-xl-1{padding:.25rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.p-xl-2{padding:.5rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.p-xl-3{padding:1rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.p-xl-4{padding:1.5rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.p-xl-5{padding:3rem!important}.m-xl-auto{margin:auto!important}}.e-px{padding-left:0;padding-right:0}@media (min-width:576px){.e-px{padding-left:5%;padding-right:5%}}@media (min-width:768px){.e-px{padding-left:10%;padding-right:10%}}.comments-list img,.img-fluid,.modal-dialog.cascading-modal.modal-avatar .modal-header,.reply-form img,.section-blog-fw .view img{max-width:100%;height:auto}.inline-ul>li{display:inline}.list-inline-div>div{display:inline-block}@media only screen and (max-width:992px){.center-on-small-only{text-align:center}.center-on-small-only .comments-list img,.center-on-small-only .img-fluid,.center-on-small-only .modal-dialog.cascading-modal.modal-avatar .modal-header,.center-on-small-only .reply-form img,.center-on-small-only .section-blog-fw .view img,.comments-list .center-on-small-only img,.modal-dialog.cascading-modal.modal-avatar .center-on-small-only .modal-header,.reply-form .center-on-small-only img,.section-blog-fw .view .center-on-small-only img{display:inline}}.card .card-circle,.card-overlay,.flex-center,.section.team-section .avatar,.testimonial-carousel .testimonial .avatar{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:100%}.divider-new:after,.divider-new:before{content:'';height:1.5px;background:#c6c6c6}.card .card-circle p,.card-overlay p,.flex-center p,.section.team-section .avatar p,.testimonial-carousel .testimonial .avatar p{margin:0}.card .card-circle ul li,.card-overlay ul li,.flex-center ul li,.section.team-section .avatar ul li,.testimonial-carousel .testimonial .avatar ul li{margin-bottom:1rem}@media (min-width:992px){.e-px{padding-left:15%;padding-right:15%}.mb-r{margin-bottom:3rem!important}}@media (max-width:992px){.hidden-md-down{display:none!important}.mb-r{margin-bottom:2rem!important}.navbar .container{width:100%}.navbar .container .navbar-toggler-right{right:0}}.font-bold{font-weight:500}.hr-light{border-top:1px solid #fff}.hr-dark{border-top:1px solid #666}.blockquote .bq-title{font-weight:400;font-size:1.5rem;margin-bottom:0}.divider-new,body,h1,h2,h3,h4,h5,h6{font-weight:300}.blockquote p{font-size:1.1rem}.bq-primary{border-left:3px solid #4285F4}.bq-primary .bq-title{color:#4285F4}.bq-warning{border-left:3px solid #fb3}.bq-warning .bq-title{color:#fb3}.bq-danger{border-left:3px solid #ff3547}.bq-danger .bq-title{color:#ff3547}.bq-success{border-left:3px solid #00C851}.bq-success .bq-title{color:#00C851}@font-face{font-family:"Swiss 721 W01 Thin";src:url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.eot);src:url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.eot?#iefix) format("embedded-opentype"),url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.woff) format("woff"),url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.ttf) format("truetype"),url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-thin-webfont.svg#swis721_th_btthin) format("svg");font-weight:400;font-style:normal}@font-face{font-family:"Swiss 721 W01 Light";src:url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.eot);src:url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.eot?#iefix) format("embedded-opentype"),url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.woff) format("woff"),url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.ttf) format("truetype"),url(https://s3.amazonaws.com/smartapp-icons/Partner/fonts/swiss-721-light-webfont.svg#swis721_lt_btlight) format("svg");font-weight:400;font-style:normal}body{font-family:Roboto,"Swiss 721 W01 Thin",sans-serif}.h1-responsive,.section-heading h1{font-size:150%}.h2-responsive,.section-blog-fw h2{font-size:145%}.h3-responsive,.h4-responsive,.h5-responsive{font-size:135%}@media (min-width:576px){.h1-responsive,.section-heading h1{font-size:170%}.h2-responsive,.section-blog-fw h2{font-size:140%}.h3-responsive,.h4-responsive,.h5-responsive{font-size:125%}}@media (min-width:768px){.h1-responsive,.section-heading h1{font-size:200%}.h2-responsive,.section-blog-fw h2{font-size:170%}.h3-responsive{font-size:140%}.h4-responsive,.h5-responsive{font-size:125%}}@media (min-width:992px){.h1-responsive,.section-heading h1{font-size:200%}.h2-responsive,.section-blog-fw h2{font-size:170%}.h3-responsive{font-size:140%}.h4-responsive,.h5-responsive{font-size:125%}}@media (min-width:1200px){.e-px{padding-left:20%;padding-right:20%}.h1-responsive,.section-heading h1{font-size:250%}.h2-responsive,.section-blog-fw h2{font-size:200%}.h3-responsive{font-size:170%}.h4-responsive{font-size:140%}.h5-responsive{font-size:125%}}.fs-0{font-size:0!important}.fs-1{font-size:.25rem!important}.fs-2{font-size:.5rem!important}.fs-3{font-size:1rem!important}.fs-4{font-size:1.5rem!important}.fs-5{font-size:3rem!important}.divider-new{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;margin-top:45px;margin-bottom:45px}.card,.card .card-body h3,.card .card-body h4,.card .card-text{font-weight:400}.divider-new h2{margin-top:5px}.divider-new:before{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;margin:0 .45em 0 0}.divider-new:after{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;margin:0 0 0 .45em}blockquote{padding:.5rem 1rem;font-size:1.25rem;border-left:.25rem solid #eceeef}blockquote p{font-size:.9rem;padding-left:2rem;padding-top:1rem;padding-bottom:1rem}.btn{font-size:.8rem;padding:.85rem 2.13rem;margin:6px;border-radius:2px;border:0;-webkit-transition:.2s ease-out;transition:.2s ease-out;white-space:normal!important;cursor:pointer}.btn:active,.btn:focus,.btn:hover{outline:0}.btn .fa{font-size:1rem;margin-top:-2px}.btn .fa.right{margin-left:3px}.btn .fa.left{margin-right:3px}.btn.btn-lg{font-size:.9rem;padding:1rem 2.4rem}.btn.btn-lg .fa{font-size:1.2rem}.btn.btn-md{font-size:.7rem;padding:.7rem 1.6rem}.btn.btn-md .fa{font-size:.9rem}.btn.btn-sm,.btn.wishlist{font-size:.6rem;padding:.5rem 1.6rem}.btn.btn-sm.btn-table,.btn.btn-table.wishlist{padding:.5rem .9rem}.btn.btn-sm .fa,.btn.wishlist .fa{font-size:.7rem}.btn.btn-tb{padding:.3rem 1rem}.btn.disabled,.btn:disabled{cursor:not-allowed;pointer-events:none}.btn[class*=btn-outline-]{padding-top:.76rem;padding-bottom:.76rem}.btn[class*=btn-outline-].btn-sm,.btn[class*=btn-outline-].wishlist{padding-top:.42rem;padding-bottom:.42rem}.btn[class*=btn-outline-].btn-md{padding-top:.58rem;padding-bottom:.58rem}.btn[class*=btn-outline-].btn-lg{padding-top:.9rem;padding-bottom:.9rem}.btn-secondary.disabled,.btn-secondary:disabled{background-color:#b579d2!important;border-color:#b579d2!important}.btn-group .btn{margin:0}.btn-block{margin:inherit}.btn-split{padding-left:.85rem;padding-right:1.25rem}.btn-link,.btn-link:focus,.btn-link:hover{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-primary{background-color:#4285F4}.btn-primary:hover{background-color:#5a95f5!important}.btn-primary.active,.btn-primary:active,.btn-primary:focus{background-color:#0d5bdd!important}.btn-primary.dropdown-toggle{background-color:#4285F4!important}.btn-primary.dropdown-toggle:focus,.btn-primary.dropdown-toggle:hover{background-color:#5a95f5!important}.btn-outline-primary{border:2px solid #4285F4;color:#4285F4!important;background-color:transparent}.btn-outline-primary.active,.btn-outline-primary:active,.btn-outline-primary:active:focus,.btn-outline-primary:focus,.btn-outline-primary:hover{background-color:transparent;color:#4285F4;border-color:#4285F4}.btn-danger{background-color:#ff3547}.btn-danger:hover{background-color:#ff4f5e!important}.btn-danger.active,.btn-danger:active,.btn-danger:focus{background-color:#e80015!important}.btn-danger.dropdown-toggle{background-color:#ff3547!important}.btn-danger.dropdown-toggle:focus,.btn-danger.dropdown-toggle:hover{background-color:#ff4f5e!important}.btn-outline-danger{border:2px solid #ff3547;color:#ff3547!important;background-color:transparent}.btn-outline-danger.active,.btn-outline-danger:active,.btn-outline-danger:active:focus,.btn-outline-danger:focus,.btn-outline-danger:hover{background-color:transparent;color:#ff3547;border-color:#ff3547}.btn-warning{background-color:#F80}.btn-warning:hover{background-color:#ff941a!important}.btn-warning.active,.btn-warning:active,.btn-warning:focus{background-color:#b35f00!important}.btn-warning.dropdown-toggle{background-color:#F80!important}.btn-warning.dropdown-toggle:focus,.btn-warning.dropdown-toggle:hover{background-color:#ff941a!important}.btn-outline-warning{border:2px solid #F80;color:#F80!important;background-color:transparent}.btn-outline-warning.active,.btn-outline-warning:active,.btn-outline-warning:active:focus,.btn-outline-warning:focus,.btn-outline-warning:hover{background-color:transparent;color:#F80;border-color:#F80}.btn-success{background-color:#00C851}.btn-success:hover{background-color:#00e25b!important}.btn-success.active,.btn-success:active,.btn-success:focus{background-color:#007c32!important}.btn-success.dropdown-toggle{background-color:#00C851!important}.btn-success.dropdown-toggle:focus,.btn-success.dropdown-toggle:hover{background-color:#00e25b!important}.btn-outline-success{border:2px solid #00C851;color:#00C851!important;background-color:transparent}.btn-outline-success.active,.btn-outline-success:active,.btn-outline-success:active:focus,.btn-outline-success:focus,.btn-outline-success:hover{background-color:transparent;color:#00C851;border-color:#00C851}.btn-info{background-color:#33b5e5}.btn-info:hover{background-color:#4abde8!important}.btn-info.active,.btn-info:active,.btn-info:focus{background-color:#178ab4!important}.btn-info.dropdown-toggle{background-color:#33b5e5!important}.btn-info.dropdown-toggle:focus,.btn-info.dropdown-toggle:hover{background-color:#4abde8!important}.btn-outline-info{border:2px solid #33b5e5;color:#33b5e5!important;background-color:transparent}.btn-outline-info.active,.btn-outline-info:active,.btn-outline-info:active:focus,.btn-outline-info:focus,.btn-outline-info:hover{background-color:transparent;color:#33b5e5;border-color:#33b5e5}.btn-default{background-color:#2BBBAD}.btn-default:hover{background-color:#30cfc0!important}.btn-default.active,.btn-default:active,.btn-default:focus{background-color:#1d7d73!important}.btn-default.dropdown-toggle{background-color:#2BBBAD!important}.btn-default.dropdown-toggle:focus,.btn-default.dropdown-toggle:hover{background-color:#30cfc0!important}.btn-outline-default{border:2px solid #2BBBAD;color:#2BBBAD!important;background-color:transparent}.btn-outline-default.active,.btn-outline-default:active,.btn-outline-default:active:focus,.btn-outline-default:focus,.btn-outline-default:hover{background-color:transparent;color:#2BBBAD;border-color:#2BBBAD}.btn-secondary{background-color:#a6c}.btn-secondary:hover{background-color:#b579d2!important}.btn-secondary.active,.btn-secondary:active,.btn-secondary:focus{background-color:#8639ac!important}.btn-secondary.dropdown-toggle{background-color:#a6c!important}.btn-secondary.dropdown-toggle:focus,.btn-secondary.dropdown-toggle:hover{background-color:#b579d2!important}.btn-outline-secondary{border:2px solid #a6c;color:#a6c!important;background-color:transparent}.btn-outline-secondary.active,.btn-outline-secondary:active,.btn-outline-secondary:active:focus,.btn-outline-secondary:focus,.btn-outline-secondary:hover{background-color:transparent;color:#a6c;border-color:#a6c}.btn-elegant{background-color:#2E2E2E}.btn-elegant:hover{background-color:#3b3b3b!important}.btn-elegant.active,.btn-elegant:active,.btn-elegant:focus{background-color:#080808!important}.btn-elegant.dropdown-toggle{background-color:#2E2E2E!important}.btn-elegant.dropdown-toggle:focus,.btn-elegant.dropdown-toggle:hover{background-color:#3b3b3b!important}.btn-outline-elegant{border:2px solid #2E2E2E;color:#2E2E2E!important;background-color:transparent}.btn-outline-elegant.active,.btn-outline-elegant:active,.btn-outline-elegant:active:focus,.btn-outline-elegant:focus,.btn-outline-elegant:hover{background-color:transparent;color:#2E2E2E;border-color:#2E2E2E}.btn-unique{background-color:#880e4f}.btn-unique:hover{background-color:#9f105c!important}.btn-unique.active,.btn-unique:active,.btn-unique:focus{background-color:#430727!important}.btn-unique.dropdown-toggle{background-color:#880e4f!important}.btn-unique.dropdown-toggle:focus,.btn-unique.dropdown-toggle:hover{background-color:#9f105c!important}.btn-outline-unique{border:2px solid #880e4f;color:#880e4f!important;background-color:transparent}.btn-outline-unique.active,.btn-outline-unique:active,.btn-outline-unique:active:focus,.btn-outline-unique:focus,.btn-outline-unique:hover{background-color:transparent;color:#880e4f;border-color:#880e4f}.btn-dark-green{background-color:#388E3C}.btn-dark-green:hover{background-color:#3fa044!important}.btn-dark-green.active,.btn-dark-green:active,.btn-dark-green:focus{background-color:#225725!important}.btn-dark-green.dropdown-toggle{background-color:#388E3C!important}.btn-dark-green.dropdown-toggle:focus,.btn-dark-green.dropdown-toggle:hover{background-color:#3fa044!important}.btn-outline-dark-green{border:2px solid #388E3C;color:#388E3C!important;background-color:transparent}.btn-outline-dark-green.active,.btn-outline-dark-green:active,.btn-outline-dark-green:active:focus,.btn-outline-dark-green:focus,.btn-outline-dark-green:hover{background-color:transparent;color:#388E3C;border-color:#388E3C}.btn-mdb-color{background-color:#59698D}.btn-mdb-color:hover{background-color:#63759d!important}.btn-mdb-color.active,.btn-mdb-color:active,.btn-mdb-color:focus{background-color:#3b465e!important}.btn-mdb-color.dropdown-toggle{background-color:#59698D!important}.btn-mdb-color.dropdown-toggle:focus,.btn-mdb-color.dropdown-toggle:hover{background-color:#63759d!important}.btn-outline-mdb-color{border:2px solid #59698D;color:#59698D!important;background-color:transparent}.btn-outline-mdb-color.active,.btn-outline-mdb-color:active,.btn-outline-mdb-color:active:focus,.btn-outline-mdb-color:focus,.btn-outline-mdb-color:hover{background-color:transparent;color:#59698D;border-color:#59698D}.btn-red{background-color:#D32F2F}.btn-red:hover{background-color:#d74444!important}.btn-red.active,.btn-red:active,.btn-red:focus{background-color:#962020!important}.btn-red.dropdown-toggle{background-color:#D32F2F!important}.btn-red.dropdown-toggle:focus,.btn-red.dropdown-toggle:hover{background-color:#d74444!important}.btn-outline-red{border:2px solid #D32F2F;color:#D32F2F!important;background-color:transparent}.btn-outline-red.active,.btn-outline-red:active,.btn-outline-red:active:focus,.btn-outline-red:focus,.btn-outline-red:hover{background-color:transparent;color:#D32F2F;border-color:#D32F2F}.btn-pink{background-color:#ec407a}.btn-pink:hover{background-color:#ee578a!important}.btn-pink.active,.btn-pink:active,.btn-pink:focus{background-color:#cb1452!important}.btn-pink.dropdown-toggle{background-color:#ec407a!important}.btn-pink.dropdown-toggle:focus,.btn-pink.dropdown-toggle:hover{background-color:#ee578a!important}.btn-outline-pink{border:2px solid #ec407a;color:#ec407a!important;background-color:transparent}.btn-outline-pink.active,.btn-outline-pink:active,.btn-outline-pink:active:focus,.btn-outline-pink:focus,.btn-outline-pink:hover{background-color:transparent;color:#ec407a;border-color:#ec407a}.btn-purple{background-color:#8e24aa}.btn-purple:hover{background-color:#a028bf!important}.btn-purple.active,.btn-purple:active,.btn-purple:focus{background-color:#59176b!important}.btn-purple.dropdown-toggle{background-color:#8e24aa!important}.btn-purple.dropdown-toggle:focus,.btn-purple.dropdown-toggle:hover{background-color:#a028bf!important}.btn-outline-purple{border:2px solid #8e24aa;color:#8e24aa!important;background-color:transparent}.btn-outline-purple.active,.btn-outline-purple:active,.btn-outline-purple:active:focus,.btn-outline-purple:focus,.btn-outline-purple:hover{background-color:transparent;color:#8e24aa;border-color:#8e24aa}.btn-deep-purple{background-color:#512da8}.btn-deep-purple:hover{background-color:#5b32bc!important}.btn-deep-purple.active,.btn-deep-purple:active,.btn-deep-purple:focus{background-color:#341d6c!important}.btn-deep-purple.dropdown-toggle{background-color:#512da8!important}.btn-deep-purple.dropdown-toggle:focus,.btn-deep-purple.dropdown-toggle:hover{background-color:#5b32bc!important}.btn-outline-deep-purple{border:2px solid #512da8;color:#512da8!important;background-color:transparent}.btn-outline-deep-purple.active,.btn-outline-deep-purple:active,.btn-outline-deep-purple:active:focus,.btn-outline-deep-purple:focus,.btn-outline-deep-purple:hover{background-color:transparent;color:#512da8;border-color:#512da8}.btn-indigo{background-color:#3f51b5}.btn-indigo:hover{background-color:#4d5ec1!important}.btn-indigo.active,.btn-indigo:active,.btn-indigo:focus{background-color:#2b387c!important}.btn-indigo.dropdown-toggle{background-color:#3f51b5!important}.btn-indigo.dropdown-toggle:focus,.btn-indigo.dropdown-toggle:hover{background-color:#4d5ec1!important}.btn-outline-indigo{border:2px solid #3f51b5;color:#3f51b5!important;background-color:transparent}.btn-outline-indigo.active,.btn-outline-indigo:active,.btn-outline-indigo:active:focus,.btn-outline-indigo:focus,.btn-outline-indigo:hover{background-color:transparent;color:#3f51b5;border-color:#3f51b5}.btn-blue{background-color:#1976D2}.btn-blue:hover{background-color:#2083e4!important}.btn-blue.active,.btn-blue:active,.btn-blue:focus{background-color:#11508e!important}.btn-blue.dropdown-toggle{background-color:#1976D2!important}.btn-blue.dropdown-toggle:focus,.btn-blue.dropdown-toggle:hover{background-color:#2083e4!important}.btn-outline-blue{border:2px solid #1976D2;color:#1976D2!important;background-color:transparent}.btn-outline-blue.active,.btn-outline-blue:active,.btn-outline-blue:active:focus,.btn-outline-blue:focus,.btn-outline-blue:hover{background-color:transparent;color:#1976D2;border-color:#1976D2}.btn-light-blue{background-color:#82B1FF}.btn-light-blue:hover{background-color:#9cc1ff!important}.btn-light-blue.active,.btn-light-blue:active,.btn-light-blue:focus{background-color:#3681ff!important}.btn-light-blue.dropdown-toggle{background-color:#82B1FF!important}.btn-light-blue.dropdown-toggle:focus,.btn-light-blue.dropdown-toggle:hover{background-color:#9cc1ff!important}.btn-outline-light-blue{border:2px solid #82B1FF;color:#82B1FF!important;background-color:transparent}.btn-outline-light-blue.active,.btn-outline-light-blue:active,.btn-outline-light-blue:active:focus,.btn-outline-light-blue:focus,.btn-outline-light-blue:hover{background-color:transparent;color:#82B1FF;border-color:#82B1FF}.btn-cyan{background-color:#00bcd4}.btn-cyan:hover{background-color:#00d3ee!important}.btn-cyan.active,.btn-cyan:active,.btn-cyan:focus{background-color:#007888!important}.btn-cyan.dropdown-toggle{background-color:#00bcd4!important}.btn-cyan.dropdown-toggle:focus,.btn-cyan.dropdown-toggle:hover{background-color:#00d3ee!important}.btn-outline-cyan{border:2px solid #00bcd4;color:#00bcd4!important;background-color:transparent}.btn-outline-cyan.active,.btn-outline-cyan:active,.btn-outline-cyan:active:focus,.btn-outline-cyan:focus,.btn-outline-cyan:hover{background-color:transparent;color:#00bcd4;border-color:#00bcd4}.btn-teal{background-color:#00796b}.btn-teal:hover{background-color:#009382!important}.btn-teal.active,.btn-teal:active,.btn-teal:focus{background-color:#002d27!important}.btn-teal.dropdown-toggle{background-color:#00796b!important}.btn-teal.dropdown-toggle:focus,.btn-teal.dropdown-toggle:hover{background-color:#009382!important}.btn-outline-teal{border:2px solid #00796b;color:#00796b!important;background-color:transparent}.btn-outline-teal.active,.btn-outline-teal:active,.btn-outline-teal:active:focus,.btn-outline-teal:focus,.btn-outline-teal:hover{background-color:transparent;color:#00796b;border-color:#00796b}.btn-green{background-color:#388E3C}.btn-green:hover{background-color:#3fa044!important}.btn-green.active,.btn-green:active,.btn-green:focus{background-color:#225725!important}.btn-green.dropdown-toggle{background-color:#388E3C!important}.btn-green.dropdown-toggle:focus,.btn-green.dropdown-toggle:hover{background-color:#3fa044!important}.btn-outline-green{border:2px solid #388E3C;color:#388E3C!important;background-color:transparent}.btn-outline-green.active,.btn-outline-green:active,.btn-outline-green:active:focus,.btn-outline-green:focus,.btn-outline-green:hover{background-color:transparent;color:#388E3C;border-color:#388E3C}.btn-light-green{background-color:#8bc34a}.btn-light-green:hover{background-color:#97c95d!important}.btn-light-green.active,.btn-light-green:active,.btn-light-green:focus{background-color:#649130!important}.btn-light-green.dropdown-toggle{background-color:#8bc34a!important}.btn-light-green.dropdown-toggle:focus,.btn-light-green.dropdown-toggle:hover{background-color:#97c95d!important}.btn-outline-light-green{border:2px solid #8bc34a;color:#8bc34a!important;background-color:transparent}.btn-outline-light-green.active,.btn-outline-light-green:active,.btn-outline-light-green:active:focus,.btn-outline-light-green:focus,.btn-outline-light-green:hover{background-color:transparent;color:#8bc34a;border-color:#8bc34a}.btn-lime{background-color:#afb42b}.btn-lime:hover{background-color:#c3c930!important}.btn-lime.active,.btn-lime:active,.btn-lime:focus{background-color:#73761c!important}.btn-lime.dropdown-toggle{background-color:#afb42b!important}.btn-lime.dropdown-toggle:focus,.btn-lime.dropdown-toggle:hover{background-color:#c3c930!important}.btn-outline-lime{border:2px solid #afb42b;color:#afb42b!important;background-color:transparent}.btn-outline-lime.active,.btn-outline-lime:active,.btn-outline-lime:active:focus,.btn-outline-lime:focus,.btn-outline-lime:hover{background-color:transparent;color:#afb42b;border-color:#afb42b}.btn-yellow{background-color:#fbc02d}.btn-yellow:hover{background-color:#fbc846!important}.btn-yellow.active,.btn-yellow:active,.btn-yellow:focus{background-color:#d79b04!important}.btn-yellow.dropdown-toggle{background-color:#fbc02d!important}.btn-yellow.dropdown-toggle:focus,.btn-yellow.dropdown-toggle:hover{background-color:#fbc846!important}.btn-outline-yellow{border:2px solid #fbc02d;color:#fbc02d!important;background-color:transparent}.btn-outline-yellow.active,.btn-outline-yellow:active,.btn-outline-yellow:active:focus,.btn-outline-yellow:focus,.btn-outline-yellow:hover{background-color:transparent;color:#fbc02d;border-color:#fbc02d}.btn-amber{background-color:#ffa000}.btn-amber:hover{background-color:#ffaa1a!important}.btn-amber.active,.btn-amber:active,.btn-amber:focus{background-color:#b37000!important}.btn-amber.dropdown-toggle{background-color:#ffa000!important}.btn-amber.dropdown-toggle:focus,.btn-amber.dropdown-toggle:hover{background-color:#ffaa1a!important}.btn-outline-amber{border:2px solid #ffa000;color:#ffa000!important;background-color:transparent}.btn-outline-amber.active,.btn-outline-amber:active,.btn-outline-amber:active:focus,.btn-outline-amber:focus,.btn-outline-amber:hover{background-color:transparent;color:#ffa000;border-color:#ffa000}.btn-orange{background-color:#f57c00}.btn-orange:hover{background-color:#ff8910!important}.btn-orange.active,.btn-orange:active,.btn-orange:focus{background-color:#a95500!important}.btn-orange.dropdown-toggle{background-color:#f57c00!important}.btn-orange.dropdown-toggle:focus,.btn-orange.dropdown-toggle:hover{background-color:#ff8910!important}.btn-outline-orange{border:2px solid #f57c00;color:#f57c00!important;background-color:transparent}.btn-outline-orange.active,.btn-outline-orange:active,.btn-outline-orange:active:focus,.btn-outline-orange:focus,.btn-outline-orange:hover{background-color:transparent;color:#f57c00;border-color:#f57c00}.btn-deep-orange{background-color:#ff7043}.btn-deep-orange:hover{background-color:#ff835d!important}.btn-deep-orange.active,.btn-deep-orange:active,.btn-deep-orange:focus{background-color:#f63b00!important}.btn-deep-orange.dropdown-toggle{background-color:#ff7043!important}.btn-deep-orange.dropdown-toggle:focus,.btn-deep-orange.dropdown-toggle:hover{background-color:#ff835d!important}.btn-outline-deep-orange{border:2px solid #ff7043;color:#ff7043!important;background-color:transparent}.btn-outline-deep-orange.active,.btn-outline-deep-orange:active,.btn-outline-deep-orange:active:focus,.btn-outline-deep-orange:focus,.btn-outline-deep-orange:hover{background-color:transparent;color:#ff7043;border-color:#ff7043}.btn-brown{background-color:#795548}.btn-brown:hover{background-color:#896052!important}.btn-brown.active,.btn-brown:active,.btn-brown:focus{background-color:#49332b!important}.btn-brown.dropdown-toggle{background-color:#795548!important}.btn-brown.dropdown-toggle:focus,.btn-brown.dropdown-toggle:hover{background-color:#896052!important}.btn-outline-brown{border:2px solid #795548;color:#795548!important;background-color:transparent}.btn-outline-brown.active,.btn-outline-brown:active,.btn-outline-brown:active:focus,.btn-outline-brown:focus,.btn-outline-brown:hover{background-color:transparent;color:#795548;border-color:#795548}.btn-grey{background-color:#616161}.btn-grey:hover{background-color:#6e6e6e!important}.btn-grey.active,.btn-grey:active,.btn-grey:focus{background-color:#3b3b3b!important}.btn-grey.dropdown-toggle{background-color:#616161!important}.btn-grey.dropdown-toggle:focus,.btn-grey.dropdown-toggle:hover{background-color:#6e6e6e!important}.btn-outline-grey{border:2px solid #616161;color:#616161!important;background-color:transparent}.btn-outline-grey.active,.btn-outline-grey:active,.btn-outline-grey:active:focus,.btn-outline-grey:focus,.btn-outline-grey:hover{background-color:transparent;color:#616161;border-color:#616161}.btn-blue-grey{background-color:#78909c}.btn-blue-grey:hover{background-color:#879ca7!important}.btn-blue-grey.active,.btn-blue-grey:active,.btn-blue-grey:focus{background-color:#546973!important}.btn-blue-grey.dropdown-toggle{background-color:#78909c!important}.btn-blue-grey.dropdown-toggle:focus,.btn-blue-grey.dropdown-toggle:hover{background-color:#879ca7!important}.btn-outline-blue-grey{border:2px solid #78909c;color:#78909c!important;background-color:transparent}.btn-outline-blue-grey.active,.btn-outline-blue-grey:active,.btn-outline-blue-grey:active:focus,.btn-outline-blue-grey:focus,.btn-outline-blue-grey:hover{background-color:transparent;color:#78909c;border-color:#78909c}.btn-white{background-color:#fff}.btn-white:hover{background-color:#fff!important}.btn-white.active,.btn-white:active,.btn-white:focus{background-color:#d9d9d9!important}.btn-white.dropdown-toggle,.btn-white.dropdown-toggle:focus,.btn-white.dropdown-toggle:hover{background-color:#fff!important}.btn-outline-white{border:2px solid #fff;color:#fff!important;background-color:transparent}.btn-outline-white.active,.btn-outline-white:active,.btn-outline-white:active:focus,.btn-outline-white:focus,.btn-outline-white:hover{background-color:transparent;color:#fff;border-color:#fff}.btn-black{background-color:#000}.btn-black:hover{background-color:#0d0d0d!important}.btn-black.active,.btn-black.dropdown-toggle,.btn-black:active,.btn-black:focus{background-color:#000!important}.btn-black.dropdown-toggle:focus,.btn-black.dropdown-toggle:hover{background-color:#0d0d0d!important}.btn-outline-black{border:2px solid #000;color:#000!important;background-color:transparent}.btn-outline-black.active,.btn-outline-black:active,.btn-outline-black:active:focus,.btn-outline-black:focus,.btn-outline-black:hover{background-color:transparent;color:#000;border-color:#000}.card{border-radius:.3rem}.card:not([class*=card-outline-]){border:0}.card img{border-radius:2px 2px 0 0}.card .card-body h5{margin-bottom:1rem;font-size:1rem;font-weight:400}.card .card-body p{margin-bottom:1rem}.card .card-title a,.card .card-title a:hover{-webkit-transition:.3s;transition:.3s}.card .card-text{font-size:.9rem;color:#747373}.card .card-footer.links-light a{font-size:15px;color:#757575}.card .card-footer.links-light a:hover{color:#d50000;-webkit-transition:.4s;transition:.4s}.card .card-footer.links-light a .fa{font-size:17px}.dropdown .dropdown-menu .dropdown-item:active,.dropdown .dropdown-menu .dropdown-item:focus,.dropdown .dropdown-menu .dropdown-item:hover{color:#1d1e1f;background-color:#f7f7f9}.navbar{font-weight:300;padding-right:1rem!important}.navbar form input{margin:0 5px 1px 8px;height:1rem}.navbar .navbar-brand{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;overflow:visible}.navbar .breadcrumb{margin:0;background-color:inherit;font-weight:300;font-size:15px;padding:.3em 0 0 1em}.navbar .navbar-toggler{border-width:0}.navbar .nav-flex-icons,.navbar.double-nav{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.navbar.navbar-dark .navbar-nav .nav-item .nav-link.disabled,.navbar.navbar-dark .navbar-nav .nav-item .nav-link.disabled:hover{color:rgba(255,255,255,.5)}.navbar.navbar-light .navbar-nav .nav-item .nav-link.disabled,.navbar.navbar-light .navbar-nav .nav-item .nav-link.disabled:hover{color:rgba(0,0,0,.5)}.navbar .nav-item .nav-link{display:block}.navbar .nav-item .nav-link.disabled:active{pointer-events:none}.navbar .nav-item .nav-link .fa{padding-left:3px;padding-right:3px}@media (max-width:992px){.navbar .nav-item .nav-link{padding-left:6px;padding-right:6px}}.navbar .dropdown-menu{position:absolute!important;margin-top:0}.navbar .dropdown-menu a{font-size:.9375rem;font-weight:300;padding:10px;color:#000!important}.navbar .dropdown-menu a:hover{color:#fff!important}@media (max-width:600px){.navbar .dropdown-menu.dropdown-menu-right{right:auto!important}}.navbar.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.9)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");cursor:pointer}.navbar.navbar-light .breadcrumb .nav-item .nav-link,.navbar.navbar-light .navbar-nav .nav-item .nav-link{color:#000;-webkit-transition:.35s;transition:.35s}.navbar.navbar-light .breadcrumb .nav-item .nav-link:hover,.navbar.navbar-light .navbar-nav .nav-item .nav-link:hover{color:rgba(0,0,0,.75)}.navbar.navbar-light .breadcrumb .nav-item.active>.nav-link:hover,.navbar.navbar-light .navbar-nav .nav-item.active>.nav-link:hover,.navbar.navbar-light .navbar-toggler,.navbar.navbar-light form .form-control{color:#000}.navbar.navbar-light .breadcrumb .nav-item.active>.nav-link,.navbar.navbar-light .navbar-nav .nav-item.active>.nav-link{background-color:rgba(0,0,0,.1)}.navbar.navbar-light form input[type=text]{border-bottom:1px solid #000}.navbar.navbar-light form input[type=text]:focus:not([readonly]){border-color:#4285F4}.navbar.navbar-light form .form-control:-moz-placeholder{color:#000;font-weight:300}.navbar.navbar-light form .form-control::-ms-placeholder{color:#000;font-weight:300}.navbar.navbar-light form .form-control::-webkit-input-placeholder{color:#000;font-weight:300}.navbar.navbar-light form .form-control::-moz-placeholder{color:#000;font-weight:300}.navbar.navbar-light form .form-control:-ms-input-placeholder{color:#000;font-weight:300}.navbar.navbar-light form .form-control::placeholder{color:#000;font-weight:300}.navbar.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.9)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");cursor:pointer}.navbar.navbar-dark .breadcrumb .nav-item .nav-link,.navbar.navbar-dark .navbar-nav .nav-item .nav-link{color:#fff;-webkit-transition:.35s;transition:.35s}.navbar.navbar-dark .breadcrumb .nav-item .nav-link:hover,.navbar.navbar-dark .navbar-nav .nav-item .nav-link:hover{color:rgba(255,255,255,.75)}.badge,.navbar.navbar-dark .breadcrumb .nav-item.active>.nav-link:hover,.navbar.navbar-dark .navbar-nav .nav-item.active>.nav-link:hover,.navbar.navbar-dark .navbar-toggler,.navbar.navbar-dark form .form-control,.pagination .active .page-link:hover{color:#fff}.navbar.navbar-dark .breadcrumb .nav-item.active>.nav-link,.navbar.navbar-dark .navbar-nav .nav-item.active>.nav-link{background-color:rgba(255,255,255,.1)}.navbar.navbar-dark form input[type=text]{border-bottom:1px solid #fff}.navbar.navbar-dark form input[type=text]:focus:not([readonly]){border-color:#4285F4}.navbar.navbar-dark form .form-control:-moz-placeholder{color:#fff;font-weight:300}.navbar.navbar-dark form .form-control::-ms-placeholder{color:#fff;font-weight:300}.navbar.navbar-dark form .form-control::-webkit-input-placeholder{color:#fff;font-weight:300}.navbar.navbar-dark form .form-control::-moz-placeholder{color:#fff;font-weight:300}.navbar.navbar-dark form .form-control:-ms-input-placeholder{color:#fff;font-weight:300}.navbar.navbar-dark form .form-control::placeholder{color:#fff;font-weight:300}.navbar.scrolling-navbar{z-index:100}@media (min-width:600px){.navbar.scrolling-navbar{-webkit-transition:background .5s ease-in-out,padding .5s ease-in-out;transition:background .5s ease-in-out,padding .5s ease-in-out;padding-top:12px;padding-bottom:12px}.navbar.scrolling-navbar .navbar-nav>li{-webkit-transition-duration:1s;transition-duration:1s}.navbar.scrolling-navbar.top-nav-collapse{padding-top:5px;padding-bottom:5px}.intro-margin.view{overflow:visible;margin-top:-56px}}.pagination .active .page-link{border-radius:2px;-webkit-transition:all .2s linear;transition:all .2s linear}.pagination.pagination-circle .page-link{border-radius:50%;margin-left:2px;margin-right:2px}.pagination.pagination-circle .active .page-link,.pagination.pagination-circle .page-link:hover{border-radius:50%}.pagination .page-link{background-color:transparent;font-size:.8rem;border:0;-webkit-transition:all .3s linear;transition:all .3s linear}.pagination .page-link:hover{-webkit-transition:all .3s linear;transition:all .3s linear;background-color:#eee}.pagination .page-link:focus{background-color:transparent}.pagination.pg-blue .active .page-link{background-color:#4285F4}.pagination.pg-red .active .page-link{background-color:#ff3547}.pagination.pg-teal .active .page-link{background-color:#2BBBAD}.pagination.pg-darkgrey .active .page-link{background-color:#37474F}.pagination.pg-dark .active .page-link{background-color:#2E2E2E}.pagination.pg-bluegrey .active .page-link{background-color:#3F729B}.pagination.pg-amber .active .page-link{background-color:#ff6f00}.pagination.pg-purple .active .page-link{background-color:#5e35b1}.badge-primary{background-color:#4285F4}.badge-danger{background-color:#ff3547}.badge-warning{background-color:#F80;color:#FFF!important}.badge-success{background-color:#00C851}.badge-info{background-color:#33b5e5}.badge-default{background-color:#2BBBAD}.badge-secondary{background-color:#a6c}.badge-elegant{background-color:#2E2E2E}.badge-unique{background-color:#880e4f}.badge-dark-green{background-color:#388E3C}.badge-mdb-color{background-color:#59698D}.badge-red{background-color:#D32F2F}.badge-pink{background-color:#ec407a}.badge-purple{background-color:#8e24aa}.badge-deep-purple{background-color:#512da8}.badge-indigo{background-color:#3f51b5}.badge-blue{background-color:#1976D2}.badge-light-blue{background-color:#82B1FF}.badge-cyan{background-color:#00bcd4}.badge-teal{background-color:#00796b}.badge-green{background-color:#388E3C}.badge-light-green{background-color:#8bc34a}.badge-lime{background-color:#afb42b}.badge-yellow{background-color:#fbc02d}.badge-amber{background-color:#ffa000}.badge-orange{background-color:#f57c00}.badge-deep-orange{background-color:#ff7043}.badge-brown{background-color:#795548}.badge-grey{background-color:#616161}.badge-blue-grey{background-color:#78909c}.badge-white{background-color:#fff}.badge-black{background-color:#000}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.modal,body.modal-open{padding-right:0!important}body.modal-open{overflow:auto}body.scrollable{overflow-y:auto}.modal-dialog .modal-content{border-radius:2px;border:0}@media (min-width:768px){.modal .modal-dialog.modal-top{top:0}.modal .modal-dialog.modal-left{left:0}.modal .modal-dialog.modal-right{right:0}.modal .modal-dialog.modal-bottom{bottom:0}.modal .modal-dialog.modal-top-left{top:10px;left:10px}.modal .modal-dialog.modal-top-right{top:10px;right:10px}.modal .modal-dialog.modal-bottom-left{left:10px;bottom:10px}.modal .modal-dialog.modal-bottom-right{right:10px;bottom:10px}}.modal.fade.top:not(.show) .modal-dialog{-webkit-transform:translate3d(0,-25%,0);transform:translate3d(0,-25%,0)}.modal.fade.left:not(.show) .modal-dialog{-webkit-transform:translate3d(-25%,0,0);transform:translate3d(-25%,0,0)}.modal.fade.right:not(.show) .modal-dialog{-webkit-transform:translate3d(25%,0,0);transform:translate3d(25%,0,0)}.modal.fade.bottom:not(.show) .modal-dialog{-webkit-transform:translate3d(0,25%,0);transform:translate3d(0,25%,0)}@media (min-width:992px){.modal .modal-fluid,.modal .modal-frame{width:100%;max-width:100%}.modal.modal-scrolling{position:relative}.modal.modal-scrolling .modal-dialog{position:fixed;z-index:1050}.modal.modal-content-clickable{top:auto;bottom:auto}.modal.modal-content-clickable .modal-dialog{position:fixed}.modal .modal-frame,.modal .modal-full-height{position:absolute;margin:0}.modal .modal-fluid .modal-content{width:100%}.modal .modal-frame.modal-bottom{bottom:0}.modal .modal-full-height{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:400px;height:100%;top:0;right:0}.modal .modal-full-height.modal-bottom,.modal .modal-full-height.modal-top{display:block;width:100%;max-width:100%;height:auto}.modal .modal-full-height.modal-top{bottom:auto}.modal .modal-full-height.modal-bottom{top:auto}.modal .modal-full-height .modal-content{width:100%}.modal .modal-full-height.modal-lg{max-width:90%;width:90%}}@media (min-width:992px) and (min-width:992px){.modal .modal-full-height.modal-lg{max-width:800px;width:800px}}@media (min-width:992px) and (min-width:1200px){.modal .modal-full-height.modal-lg{max-width:1000px;width:1000px}}@media (min-width:992px){.modal .modal-side{position:absolute;right:10px;bottom:10px;margin:0;width:400px}}.modal-dialog .btn .fa{color:#fff!important}.modal-dialog [class*=btn-outline-] .fa{color:inherit!important}.modal-dialog.cascading-modal{margin-top:10%}.modal-dialog.cascading-modal .close{color:#fff;opacity:1;text-shadow:none}.modal-dialog.cascading-modal .modal-header{text-align:center;margin:-2rem 1rem 1rem;padding:1.5rem;border:none;border-radius:3px}.modal-dialog.cascading-modal .modal-header .close{margin-right:1rem}.modal-dialog.cascading-modal .modal-header .title{width:100%;margin-bottom:0;font-size:1.25rem}.modal-dialog.cascading-modal .modal-header .title .fa{margin-right:9px}.modal-dialog.cascading-modal .modal-header .social-buttons{margin-top:1.5rem}.modal-dialog.cascading-modal .modal-header .social-buttons a{font-size:1rem}.modal-dialog.cascading-modal .modal-c-tabs .nav-tabs{margin:-1.5rem 1rem 0}.modal-dialog.cascading-modal .modal-c-tabs .tab-content{padding:1.7rem 0 0}.modal-dialog.cascading-modal .nav-tabs{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.modal-dialog.cascading-modal .nav-tabs li{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.modal-dialog.cascading-modal .nav-tabs li a{text-align:center;font-weight:400}.modal-dialog.cascading-modal .modal-body,.modal-dialog.cascading-modal .modal-footer{color:#616161;padding-right:2rem;padding-left:2rem}.modal-dialog.cascading-modal .modal-body .additional-option,.modal-dialog.cascading-modal .modal-footer .additional-option{text-align:center;margin-top:1rem}.modal-dialog.cascading-modal.modal-avatar{margin-top:6rem}.modal-dialog.cascading-modal.modal-avatar .modal-header{margin:-6rem 2rem -1rem}.modal-dialog.cascading-modal.modal-avatar .modal-header img{width:130px;margin-left:auto;margin-right:auto}.modal-dialog.modal-notify .heading{margin:0;padding:.3rem;color:#fff;font-size:1.15rem}.modal-dialog.modal-notify .modal-header{border:0}.modal-dialog.modal-notify .close{opacity:1}.modal-dialog.modal-notify .modal-body{padding:1.5rem;color:#616161}.modal-dialog.modal-notify .btn-outline-secondary-modal{background-color:transparent}.modal-dialog.modal-notify.modal-info .badge,.modal-dialog.modal-notify.modal-info .btn-primary-modal,.modal-dialog.modal-notify.modal-info .modal-header{background-color:#5394ff}.modal-dialog.modal-notify.modal-info .fa{color:#5394ff}.modal-dialog.modal-notify.modal-info .btn-primary-modal:hover{background-color:#6da4ff!important}.modal-dialog.modal-notify.modal-info .btn-primary-modal.active,.modal-dialog.modal-notify.modal-info .btn-primary-modal:active,.modal-dialog.modal-notify.modal-info .btn-primary-modal:focus{background-color:#0764ff!important}.modal-dialog.modal-notify.modal-info .btn-primary-modal.dropdown-toggle{background-color:#5394ff!important}.modal-dialog.modal-notify.modal-info .btn-primary-modal.dropdown-toggle:focus,.modal-dialog.modal-notify.modal-info .btn-primary-modal.dropdown-toggle:hover{background-color:#6da4ff!important}.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal{border:2px solid #5394ff;color:#5394ff!important;background-color:transparent}.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal.active,.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal:active,.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal:active:focus,.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal:focus,.modal-dialog.modal-notify.modal-info .btn-outline-secondary-modal:hover{background-color:transparent;color:#5394ff;border-color:#5394ff}.modal-dialog.modal-notify.modal-warning .badge,.modal-dialog.modal-notify.modal-warning .btn-primary-modal,.modal-dialog.modal-notify.modal-warning .modal-header{background-color:#ff8e38}.modal-dialog.modal-notify.modal-warning .fa{color:#ff8e38}.modal-dialog.modal-notify.modal-warning .btn-primary-modal:hover{background-color:#ff9c52!important}.modal-dialog.modal-notify.modal-warning .btn-primary-modal.active,.modal-dialog.modal-notify.modal-warning .btn-primary-modal:active,.modal-dialog.modal-notify.modal-warning .btn-primary-modal:focus{background-color:#eb6500!important}.modal-dialog.modal-notify.modal-warning .btn-primary-modal.dropdown-toggle{background-color:#ff8e38!important}.modal-dialog.modal-notify.modal-warning .btn-primary-modal.dropdown-toggle:focus,.modal-dialog.modal-notify.modal-warning .btn-primary-modal.dropdown-toggle:hover{background-color:#ff9c52!important}.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal{border:2px solid #ff8e38;color:#ff8e38!important;background-color:transparent}.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal.active,.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal:active,.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal:active:focus,.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal:focus,.modal-dialog.modal-notify.modal-warning .btn-outline-secondary-modal:hover{background-color:transparent;color:#ff8e38;border-color:#ff8e38}.modal-dialog.modal-notify.modal-success .badge,.modal-dialog.modal-notify.modal-success .btn-primary-modal,.modal-dialog.modal-notify.modal-success .modal-header{background-color:#01d36b}.modal-dialog.modal-notify.modal-success .fa{color:#01d36b}.modal-dialog.modal-notify.modal-success .btn-primary-modal:hover{background-color:#01ec78!important}.modal-dialog.modal-notify.modal-success .btn-primary-modal.active,.modal-dialog.modal-notify.modal-success .btn-primary-modal:active,.modal-dialog.modal-notify.modal-success .btn-primary-modal:focus{background-color:#018744!important}.modal-dialog.modal-notify.modal-success .btn-primary-modal.dropdown-toggle{background-color:#01d36b!important}.modal-dialog.modal-notify.modal-success .btn-primary-modal.dropdown-toggle:focus,.modal-dialog.modal-notify.modal-success .btn-primary-modal.dropdown-toggle:hover{background-color:#01ec78!important}.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal{border:2px solid #01d36b;color:#01d36b!important;background-color:transparent}.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal.active,.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal:active,.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal:active:focus,.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal:focus,.modal-dialog.modal-notify.modal-success .btn-outline-secondary-modal:hover{background-color:transparent;color:#01d36b;border-color:#01d36b}.modal-dialog.modal-notify.modal-danger .badge,.modal-dialog.modal-notify.modal-danger .btn-primary-modal,.modal-dialog.modal-notify.modal-danger .modal-header{background-color:#ff4b4b}.modal-dialog.modal-notify.modal-danger .fa{color:#ff4b4b}.modal-dialog.modal-notify.modal-danger .btn-primary-modal:hover{background-color:#ff6565!important}.modal-dialog.modal-notify.modal-danger .btn-primary-modal.active,.modal-dialog.modal-notify.modal-danger .btn-primary-modal:active,.modal-dialog.modal-notify.modal-danger .btn-primary-modal:focus{background-color:#fe0000!important}.modal-dialog.modal-notify.modal-danger .btn-primary-modal.dropdown-toggle{background-color:#ff4b4b!important}.modal-dialog.modal-notify.modal-danger .btn-primary-modal.dropdown-toggle:focus,.modal-dialog.modal-notify.modal-danger .btn-primary-modal.dropdown-toggle:hover{background-color:#ff6565!important}.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal{border:2px solid #ff4b4b;color:#ff4b4b!important;background-color:transparent}.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal.active,.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal:active,.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal:active:focus,.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal:focus,.modal-dialog.modal-notify.modal-danger .btn-outline-secondary-modal:hover{background-color:transparent;color:#ff4b4b;border-color:#ff4b4b}.progress.progress-default,.progress.progress-default .progress-bar{height:1rem}.progress.progress-wider,.progress.progress-wider .progress-bar{height:20px}.progress.progress-narrower,.progress.progress-narrower .progress-bar{height:1px}.carousel .carousel-control-next-icon,.carousel .carousel-control-prev-icon{width:36px;height:36px}.carousel .carousel-control-prev-icon{background-image:url(../img//svg/arrow_left.svg)}.carousel .carousel-control-next-icon{background-image:url(../img//svg/arrow_right.svg)}.carousel .carousel-indicators li{max-width:10px;height:10px;border-radius:50%;cursor:pointer}.carousel .video-fluid{height:100%;width:100%}.carousel-fade .carousel-item{opacity:0;-webkit-transition-duration:.6s;transition-duration:.6s;-webkit-transition-property:opacity;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev,.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}@supports (transform-style:preserve-3d){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev,.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.accordion .card{border-bottom:1px solid #eee;-webkit-box-shadow:none;box-shadow:none}.accordion .card .card-header{padding:1rem 1.5rem;background:0 0;border-bottom:0}.accordion .card .card-header a:not(.collapsed) .rotate-icon{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.accordion .card .fa-angle-down{float:right}.accordion .card .card-block{padding-top:.25rem}.accordion .card .card-body{line-height:1.7;color:#626262;font-size:.9rem;font-weight:300}.accordion .card h5{font-size:1.1rem;font-weight:400}.collapsible-body{display:none}.author-box,.jumbotron{background-color:#fff;padding:2rem}.jumbotron.m-1,.jumbotron.m-2,.jumbotron.m-3,.m-1.author-box,.m-2.author-box,.m-3.author-box,.section-blog-fw .author-box,.section-blog-fw .jumbotron{z-index:50;position:relative;margin-left:3%;margin-right:3%}.jumbotron.m-1,.m-1.author-box,.section-blog-fw .author-box,.section-blog-fw .jumbotron{margin-top:-20px}.jumbotron.m-2,.m-2.author-box{margin-top:-30px}.jumbotron.m-3,.m-3.author-box{margin-top:-40px}.view{overflow:hidden;position:relative;cursor:default}.view .mask{background-attachment:fixed}.view .full-bg-img,.view .mask{width:100%;height:100%;position:absolute;overflow:hidden;top:0;left:0}.view img,.view video{display:block;position:relative}.hm-zoom img,.hm-zoom video,.overlay img,.overlay video{-webkit-transition:all .2s linear;transition:all .2s linear}.hm-zoom:hover .mask,.overlay:hover .mask{opacity:1}.hm-zoom:hover img{-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.overlay .mask{opacity:0;-webkit-transition:all .4s ease-in-out;transition:all .4s ease-in-out}.pattern-1{background:url(../img/overlays/01.png)}.pattern-2{background:url(../img/overlays/02.png)}.pattern-3{background:url(../img/overlays/03.png)}.pattern-4{background:url(../img/overlays/04.png)}.pattern-5{background:url(../img/overlays/05.png)}.pattern-6{background:url(../img/overlays/06.png)}.pattern-7{background:url(../img/overlays/07.png)}.pattern-8{background:url(../img/overlays/08.png)}.pattern-9{background:url(../img/overlays/09.png)}.hm-blue-slight .full-bg-img,.hm-blue-slight .mask{background-color:rgba(3,169,244,.1)}.hm-red-slight .full-bg-img,.hm-red-slight .mask{background-color:rgba(244,67,54,.1)}.hm-pink-slight .full-bg-img,.hm-pink-slight .mask{background-color:rgba(233,30,99,.1)}.hm-purple-slight .full-bg-img,.hm-purple-slight .mask{background-color:rgba(156,39,176,.1)}.hm-indigo-slight .full-bg-img,.hm-indigo-slight .mask{background-color:rgba(63,81,181,.1)}.hm-cyan-slight .full-bg-img,.hm-cyan-slight .mask{background-color:rgba(0,188,212,.1)}.hm-teal-slight .full-bg-img,.hm-teal-slight .mask{background-color:rgba(0,150,136,.1)}.hm-green-slight .full-bg-img,.hm-green-slight .mask{background-color:rgba(76,175,80,.1)}.hm-lime-slight .full-bg-img,.hm-lime-slight .mask{background-color:rgba(205,220,57,.1)}.hm-yellow-slight .full-bg-img,.hm-yellow-slight .mask{background-color:rgba(255,235,59,.1)}.hm-orange-slight .full-bg-img,.hm-orange-slight .mask{background-color:rgba(255,152,0,.1)}.hm-brown-slight .full-bg-img,.hm-brown-slight .mask{background-color:rgba(121,85,72,.1)}.hm-grey-slight .full-bg-img,.hm-grey-slight .mask{background-color:rgba(158,158,158,.1)}.hm-bluegrey-slight .full-bg-img,.hm-bluegrey-slight .mask{background-color:rgba(96,125,139,.1)}.hm-black-slight .full-bg-img,.hm-black-slight .mask{background-color:rgba(0,0,0,.1)}.hm-stylish-slight .full-bg-img,.hm-stylish-slight .mask{background-color:rgba(62,69,81,.1)}.hm-white-slight .full-bg-img,.hm-white-slight .mask{background-color:rgba(255,255,255,.1)}.hm-blue-light .full-bg-img,.hm-blue-light .mask{background-color:rgba(3,169,244,.3)}.hm-red-light .full-bg-img,.hm-red-light .mask{background-color:rgba(244,67,54,.3)}.hm-pink-light .full-bg-img,.hm-pink-light .mask{background-color:rgba(233,30,99,.3)}.hm-purple-light .full-bg-img,.hm-purple-light .mask{background-color:rgba(156,39,176,.3)}.hm-indigo-light .full-bg-img,.hm-indigo-light .mask{background-color:rgba(63,81,181,.3)}.hm-cyan-light .full-bg-img,.hm-cyan-light .mask{background-color:rgba(0,188,212,.3)}.hm-teal-light .full-bg-img,.hm-teal-light .mask{background-color:rgba(0,150,136,.3)}.hm-green-light .full-bg-img,.hm-green-light .mask{background-color:rgba(76,175,80,.3)}.hm-lime-light .full-bg-img,.hm-lime-light .mask{background-color:rgba(205,220,57,.3)}.hm-yellow-light .full-bg-img,.hm-yellow-light .mask{background-color:rgba(255,235,59,.3)}.hm-orange-light .full-bg-img,.hm-orange-light .mask{background-color:rgba(255,152,0,.3)}.hm-brown-light .full-bg-img,.hm-brown-light .mask{background-color:rgba(121,85,72,.3)}.hm-grey-light .full-bg-img,.hm-grey-light .mask{background-color:rgba(158,158,158,.3)}.hm-bluegrey-light .full-bg-img,.hm-bluegrey-light .mask{background-color:rgba(96,125,139,.3)}.hm-black-light .full-bg-img,.hm-black-light .mask{background-color:rgba(0,0,0,.3)}.hm-stylish-light .full-bg-img,.hm-stylish-light .mask{background-color:rgba(62,69,81,.3)}.hm-white-light .full-bg-img,.hm-white-light .mask{background-color:rgba(255,255,255,.3)}.hm-blue-strong .full-bg-img,.hm-blue-strong .mask{background-color:rgba(3,169,244,.7)}.hm-red-strong .full-bg-img,.hm-red-strong .mask{background-color:rgba(244,67,54,.7)}.hm-pink-strong .full-bg-img,.hm-pink-strong .mask{background-color:rgba(233,30,99,.7)}.hm-purple-strong .full-bg-img,.hm-purple-strong .mask{background-color:rgba(156,39,176,.7)}.hm-indigo-strong .full-bg-img,.hm-indigo-strong .mask{background-color:rgba(63,81,181,.7)}.hm-cyan-strong .full-bg-img,.hm-cyan-strong .mask{background-color:rgba(0,188,212,.7)}.hm-teal-strong .full-bg-img,.hm-teal-strong .mask{background-color:rgba(0,150,136,.7)}.hm-green-strong .full-bg-img,.hm-green-strong .mask{background-color:rgba(76,175,80,.7)}.hm-lime-strong .full-bg-img,.hm-lime-strong .mask{background-color:rgba(205,220,57,.7)}.hm-yellow-strong .full-bg-img,.hm-yellow-strong .mask{background-color:rgba(255,235,59,.7)}.hm-orange-strong .full-bg-img,.hm-orange-strong .mask{background-color:rgba(255,152,0,.7)}.hm-brown-strong .full-bg-img,.hm-brown-strong .mask{background-color:rgba(121,85,72,.7)}.hm-grey-strong .full-bg-img,.hm-grey-strong .mask{background-color:rgba(158,158,158,.7)}.hm-bluegrey-strong .full-bg-img,.hm-bluegrey-strong .mask{background-color:rgba(96,125,139,.7)}.hm-black-strong .full-bg-img,.hm-black-strong .mask{background-color:rgba(0,0,0,.7)}.hm-stylish-strong .full-bg-img,.hm-stylish-strong .mask{background-color:rgba(62,69,81,.7)}.hm-white-strong .full-bg-img,.hm-white-strong .mask{background-color:rgba(255,255,255,.7)}.full-height,.full-height body,.full-height header,.full-height header .view{height:100%}.intro{min-height:1000px;position:relative}@media (max-width:768px){.intro{min-height:1000px}}.intro-video video{top:50%;left:50%;min-width:100%;min-height:100%;width:auto;height:auto;z-index:-100;-webkit-transform:translateX(-50%) translateY(-50%);-ms-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);background-repeat:no-repeat;background-size:cover;background-position:center center;-webkit-transition:1s opacity;transition:1s opacity}.waves-effect{position:relative;cursor:pointer;overflow:hidden;user-select:none;z-index:1}.pswp__container,.pswp__counter,.pswp__img,.pswp__share-modal{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.waves-effect .waves-ripple{position:absolute;border-radius:50%;width:100px;height:100px;margin-top:-50px;margin-left:-50px;opacity:0;background:rgba(0,0,0,.2);background:-webkit-radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);background:radial-gradient(rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,rgba(255,255,255,0) 70%);-webkit-transition:all .5s ease-out;transition:all .5s ease-out;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transform:scale(0) translate(0,0);-ms-transform:scale(0) translate(0,0);transform:scale(0) translate(0,0);pointer-events:none}.waves-effect.waves-light .waves-ripple{background:rgba(255,255,255,.4);background:-webkit-radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%);background:radial-gradient(rgba(255,255,255,.2) 0,rgba(255,255,255,.3) 40%,rgba(255,255,255,.4) 50%,rgba(255,255,255,.5) 60%,rgba(255,255,255,0) 70%)}.waves-effect.waves-classic .waves-ripple{background:rgba(0,0,0,.2)}.waves-effect.waves-classic.waves-light .waves-ripple{background:rgba(255,255,255,.4)}.waves-notransition{-webkit-transition:none!important;transition:none!important}.waves-button,.waves-circle{-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-mask-image:-webkit-radial-gradient(circle,#fff 100%,#000 100%)}.waves-button,.waves-button-input,.waves-button:hover,.waves-button:visited{white-space:nowrap;vertical-align:middle;cursor:pointer;border:none;outline:0;color:inherit;background-color:transparent;font-size:1em;line-height:1em;text-align:center;text-decoration:none;z-index:1}.waves-button{padding:.85em 1.1em;border-radius:.2em}.waves-button-input{margin:0;padding:.85em 1.1em}.waves-input-wrapper{border-radius:.2em;display:inline-block}.waves-input-wrapper.waves-button{padding:0}.waves-input-wrapper .waves-button-input{position:relative;top:0;left:0;z-index:1}.waves-circle{text-align:center;width:2.5em;height:2.5em;line-height:2.5em;border-radius:50%}.waves-float{-webkit-mask-image:none;-webkit-box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);-webkit-transition:all .3s;transition:all .3s}.waves-float:active{-webkit-box-shadow:0 8px 20px 1px rgba(0,0,0,.3);box-shadow:0 8px 20px 1px rgba(0,0,0,.3)}.waves-block{display:block}a.waves-effect,a.waves-light{display:inline-block}input[type=date],input[type=datetime-local],input[type=email],input[type=number],input[type=password],input[type=search-md],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],textarea.md-textarea{background-color:transparent;border:none;border-bottom:1px solid #bdbdbd;border-radius:0;outline:0;height:2.1rem;width:100%;font-size:1rem;-webkit-box-shadow:none;box-shadow:none;-webkit-box-sizing:content-box;box-sizing:content-box;-webkit-transition:all .3s;transition:all .3s}input[type=date]:disabled,input[type=date][readonly=readonly],input[type=datetime-local]:disabled,input[type=datetime-local][readonly=readonly],input[type=email]:disabled,input[type=email][readonly=readonly],input[type=number]:disabled,input[type=number][readonly=readonly],input[type=password]:disabled,input[type=password][readonly=readonly],input[type=search-md]:disabled,input[type=search-md][readonly=readonly],input[type=search]:disabled,input[type=search][readonly=readonly],input[type=tel]:disabled,input[type=tel][readonly=readonly],input[type=text]:disabled,input[type=text][readonly=readonly],input[type=time]:disabled,input[type=time][readonly=readonly],input[type=url]:disabled,input[type=url][readonly=readonly],textarea.md-textarea:disabled,textarea.md-textarea[readonly=readonly]{color:rgba(0,0,0,.46);border-bottom:1px dotted rgba(0,0,0,.46);background-color:transparent}input[type=date]:disabled+label,input[type=date][readonly=readonly]+label,input[type=datetime-local]:disabled+label,input[type=datetime-local][readonly=readonly]+label,input[type=email]:disabled+label,input[type=email][readonly=readonly]+label,input[type=number]:disabled+label,input[type=number][readonly=readonly]+label,input[type=password]:disabled+label,input[type=password][readonly=readonly]+label,input[type=search-md]:disabled+label,input[type=search-md][readonly=readonly]+label,input[type=search]:disabled+label,input[type=search][readonly=readonly]+label,input[type=tel]:disabled+label,input[type=tel][readonly=readonly]+label,input[type=text]:disabled+label,input[type=text][readonly=readonly]+label,input[type=time]:disabled+label,input[type=time][readonly=readonly]+label,input[type=url]:disabled+label,input[type=url][readonly=readonly]+label,textarea.md-textarea:disabled+label,textarea.md-textarea[readonly=readonly]+label{color:rgba(0,0,0,.46);background-color:transparent}input[type=date]:focus:not([readonly]),input[type=datetime-local]:focus:not([readonly]),input[type=email]:focus:not([readonly]),input[type=number]:focus:not([readonly]),input[type=password]:focus:not([readonly]),input[type=search-md]:focus:not([readonly]),input[type=search]:focus:not([readonly]),input[type=tel]:focus:not([readonly]),input[type=text]:focus:not([readonly]),input[type=time]:focus:not([readonly]),input[type=url]:focus:not([readonly]),textarea.md-textarea:focus:not([readonly]){border-bottom:1px solid #4285F4;-webkit-box-shadow:0 1px 0 0 #4285F4;box-shadow:0 1px 0 0 #4285F4}input[type=date]:focus:not([readonly])+label,input[type=datetime-local]:focus:not([readonly])+label,input[type=email]:focus:not([readonly])+label,input[type=number]:focus:not([readonly])+label,input[type=password]:focus:not([readonly])+label,input[type=search-md]:focus:not([readonly])+label,input[type=search]:focus:not([readonly])+label,input[type=tel]:focus:not([readonly])+label,input[type=text]:focus:not([readonly])+label,input[type=time]:focus:not([readonly])+label,input[type=url]:focus:not([readonly])+label,textarea.md-textarea:focus:not([readonly])+label{color:#4285F4}input[type=date].valid,input[type=date]:focus.valid,input[type=datetime-local].valid,input[type=datetime-local]:focus.valid,input[type=email].valid,input[type=email]:focus.valid,input[type=number].valid,input[type=number]:focus.valid,input[type=password].valid,input[type=password]:focus.valid,input[type=search-md].valid,input[type=search-md]:focus.valid,input[type=search].valid,input[type=search]:focus.valid,input[type=tel].valid,input[type=tel]:focus.valid,input[type=text].valid,input[type=text]:focus.valid,input[type=time].valid,input[type=time]:focus.valid,input[type=url].valid,input[type=url]:focus.valid,textarea.md-textarea.valid,textarea.md-textarea:focus.valid{border-bottom:1px solid #00C851;-webkit-box-shadow:0 1px 0 0 #00C851;box-shadow:0 1px 0 0 #00C851}input[type=date].valid+label:after,input[type=date]:focus.valid+label:after,input[type=datetime-local].valid+label:after,input[type=datetime-local]:focus.valid+label:after,input[type=email].valid+label:after,input[type=email]:focus.valid+label:after,input[type=number].valid+label:after,input[type=number]:focus.valid+label:after,input[type=password].valid+label:after,input[type=password]:focus.valid+label:after,input[type=search-md].valid+label:after,input[type=search-md]:focus.valid+label:after,input[type=search].valid+label:after,input[type=search]:focus.valid+label:after,input[type=tel].valid+label:after,input[type=tel]:focus.valid+label:after,input[type=text].valid+label:after,input[type=text]:focus.valid+label:after,input[type=time].valid+label:after,input[type=time]:focus.valid+label:after,input[type=url].valid+label:after,input[type=url]:focus.valid+label:after,textarea.md-textarea.valid+label:after,textarea.md-textarea:focus.valid+label:after{content:attr(data-success);color:#00C851;opacity:1}input[type=date].invalid,input[type=date]:focus.invalid,input[type=datetime-local].invalid,input[type=datetime-local]:focus.invalid,input[type=email].invalid,input[type=email]:focus.invalid,input[type=number].invalid,input[type=number]:focus.invalid,input[type=password].invalid,input[type=password]:focus.invalid,input[type=search-md].invalid,input[type=search-md]:focus.invalid,input[type=search].invalid,input[type=search]:focus.invalid,input[type=tel].invalid,input[type=tel]:focus.invalid,input[type=text].invalid,input[type=text]:focus.invalid,input[type=time].invalid,input[type=time]:focus.invalid,input[type=url].invalid,input[type=url]:focus.invalid,textarea.md-textarea.invalid,textarea.md-textarea:focus.invalid{border-bottom:1px solid #F44336;-webkit-box-shadow:0 1px 0 0 #F44336;box-shadow:0 1px 0 0 #F44336}input[type=date].invalid+label:after,input[type=date]:focus.invalid+label:after,input[type=datetime-local].invalid+label:after,input[type=datetime-local]:focus.invalid+label:after,input[type=email].invalid+label:after,input[type=email]:focus.invalid+label:after,input[type=number].invalid+label:after,input[type=number]:focus.invalid+label:after,input[type=password].invalid+label:after,input[type=password]:focus.invalid+label:after,input[type=search-md].invalid+label:after,input[type=search-md]:focus.invalid+label:after,input[type=search].invalid+label:after,input[type=search]:focus.invalid+label:after,input[type=tel].invalid+label:after,input[type=tel]:focus.invalid+label:after,input[type=text].invalid+label:after,input[type=text]:focus.invalid+label:after,input[type=time].invalid+label:after,input[type=time]:focus.invalid+label:after,input[type=url].invalid+label:after,input[type=url]:focus.invalid+label:after,textarea.md-textarea.invalid+label:after,textarea.md-textarea:focus.invalid+label:after{content:attr(data-error);color:#F44336;opacity:1}input[type=date]+label:after,input[type=datetime-local]+label:after,input[type=email]+label:after,input[type=number]+label:after,input[type=password]+label:after,input[type=search-md]+label:after,input[type=search]+label:after,input[type=tel]+label:after,input[type=text]+label:after,input[type=time]+label:after,input[type=url]+label:after,textarea.md-textarea+label:after{display:block;content:"";position:absolute;top:65px;opacity:0;-webkit-transition:.2s opacity ease-out,.2s color ease-out;transition:.2s opacity ease-out,.2s color ease-out}input[type=date].input-alternate,input[type=datetime-local].input-alternate,input[type=email].input-alternate,input[type=number].input-alternate,input[type=password].input-alternate,input[type=search-md].input-alternate,input[type=search].input-alternate,input[type=tel].input-alternate,input[type=text].input-alternate,input[type=time].input-alternate,input[type=url].input-alternate,textarea.md-textarea.input-alternate{padding:0 15px;height:2.1rem;-webkit-box-shadow:0 1px 3px 0 rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 2px 1px -1px rgba(0,0,0,.12);box-shadow:0 1px 3px 0 rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 2px 1px -1px rgba(0,0,0,.12);font-size:.875rem;border-bottom:0;-webkit-transition:none!important;transition:none!important}input[type=date].input-alternate:focus,input[type=date].input-alternate:hover,input[type=datetime-local].input-alternate:focus,input[type=datetime-local].input-alternate:hover,input[type=email].input-alternate:focus,input[type=email].input-alternate:hover,input[type=number].input-alternate:focus,input[type=number].input-alternate:hover,input[type=password].input-alternate:focus,input[type=password].input-alternate:hover,input[type=search-md].input-alternate:focus,input[type=search-md].input-alternate:hover,input[type=search].input-alternate:focus,input[type=search].input-alternate:hover,input[type=tel].input-alternate:focus,input[type=tel].input-alternate:hover,input[type=text].input-alternate:focus,input[type=text].input-alternate:hover,input[type=time].input-alternate:focus,input[type=time].input-alternate:hover,input[type=url].input-alternate:focus,input[type=url].input-alternate:hover,textarea.md-textarea.input-alternate:focus,textarea.md-textarea.input-alternate:hover{-webkit-box-shadow:0 3px 8px 0 rgba(0,0,0,.2),0 0 0 1px rgba(0,0,0,.08)!important;box-shadow:0 3px 8px 0 rgba(0,0,0,.2),0 0 0 1px rgba(0,0,0,.08)!important;border-bottom:0}.form-control{padding:.5rem 0 .6rem;font-size:1rem;line-height:1.5;background-color:transparent;background-image:none;border-radius:0;margin-top:.2rem;margin-bottom:1rem}.md-form,.md-form .btn{margin-bottom:1.5rem}.form-control:focus{background:0 0;-webkit-box-shadow:none;box-shadow:none}.form-control:disabled,.form-control[readonly]{background-color:transparent;border-bottom:1px solid #bdbdbd}.md-form{position:relative}.md-form label{-webkit-transition:.2s ease-out;transition:.2s ease-out;color:#757575;position:absolute;top:.8rem;left:0;font-size:1rem;cursor:text}.btn-floating,.card .card-reveal .card-title,.card-wrapper .back .card-title{cursor:pointer}.md-form label.active{-webkit-transform:translateY(-140%);-ms-transform:translateY(-140%);transform:translateY(-140%);font-size:.8rem}.md-form .prefix{-webkit-transition:color .2s;transition:color .2s;position:absolute;width:3rem;font-size:2rem;padding-top:.5rem}.btn-flat,.btn-floating{position:relative;margin:10px}.md-form .prefix~input,.md-form .prefix~textarea{margin-left:3rem;width:92%;width:-webkit-calc(100% - 3rem);width:calc(100% - 3rem)}.md-form .prefix~label{margin-left:3rem}.md-form .prefix.active{color:#4285F4}@media only screen and (max-width:992px){.md-form .prefix~input{width:86%;width:-webkit-calc(100% - 3rem);width:calc(100% - 3rem)}}@media only screen and (max-width:600px){.md-form .prefix~input{width:80%;width:-webkit-calc(100% - 3rem);width:calc(100% - 3rem)}}.md-form.form-sm input{padding-bottom:.2rem;padding-top:.2rem;font-size:.8rem;line-height:.5}.md-form.form-sm label{font-size:.9rem}.md-form.form-sm .prefix{font-size:1.5rem;top:.4rem}.md-form.form-sm .prefix~input,.md-form.form-sm .prefix~label,.md-form.form-sm .prefix~textarea{margin-left:2.2rem}.md-form.input-group{padding-left:1rem}.md-form.input-group:-moz-placeholder{color:#999;padding-top:2px}.md-form.input-group::-ms-placeholder{color:#999;padding-top:2px}.md-form.input-group::-webkit-input-placeholder{color:#999;padding-top:2px}.md-form.input-group::-moz-placeholder{color:#999;padding-top:2px}.md-form.input-group:-ms-input-placeholder{color:#999;padding-top:2px}.md-form.input-group::placeholder{color:#999;padding-top:2px}.form-group{display:block}.form-inline fieldset{margin-right:1.5rem}.form-inline .form-group{margin-right:2rem}textarea{resize:vertical;width:100%;height:3rem;background-color:transparent}textarea.md-textarea{overflow-y:hidden;padding:1.6rem 0;resize:none;min-height:3rem}.hiddendiv{display:none;white-space:pre-wrap;overflow-wrap:break-word;padding-top:1.2rem}.orange-gradient{background:-webkit-linear-gradient(50deg,#FFD86F,#FC6262);background:linear-gradient(40deg,#FFD86F,#FC6262)}.table-inverse td,.table-inverse th,.table-inverse thead th{border-color:#fff}.edge-header{display:block;height:278px;background-color:#ccc}.free-bird{margin-top:-100px}footer.page-footer{margin-top:20px;padding-top:20px;color:#fff}footer.page-footer .container-fluid{width:auto}footer.page-footer .footer-copyright{overflow:hidden;height:50px;line-height:50px;color:rgba(255,255,255,.6);background-color:rgba(0,0,0,.2);text-align:center;font-size:.9rem}footer.page-footer a{color:#fff}footer.page-footer .call-to-action{text-align:center;padding-top:1.3rem;padding-bottom:.5rem}footer.page-footer .call-to-action ul li{display:inline-block;padding-right:10px}footer.page-footer .social-section ul li{display:inline-block}footer.page-footer .social-section ul a{margin-left:0;padding-left:0}footer.page-footer ul,ul.instagram-photos{list-style-type:none;padding:0}ul.instagram-photos li{display:inline-block;max-width:100px;margin:4px}ul.instagram-photos li img{margin:0}.media .media-left{padding:0 10px 10px 0}.list-group a:hover{-webkit-transition:.5s;transition:.5s}table th{font-size:.9rem;font-weight:400}table td{font-size:.9rem;font-weight:300}.card-inverse h3,.card.card-cascade .view.gradient-card-header h2,.social-list{font-weight:400}.chip,.chips .input{font-weight:500;height:32px}table.table thead th{border-top:none}table.table td,table.table th{padding-top:1.1rem;padding-bottom:1rem}table.table a{margin:0;color:#212529}table.table .label-table{margin:0;padding:0;line-height:15px;height:15px}table.table .btn-table{margin:0 1px;padding:3px 7px}.colorful-side-nav .collapsible a,.stylish-side-nav .collapsible a{margin:0}table.table .btn-table .fa{font-size:11px}table.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075);-webkit-transition:.5s;transition:.5s}table .th-lg{min-width:9rem}table.table-sm td,table.table-sm th{padding-top:.6rem;padding-bottom:.6rem}.colorful-side-nav .collapsible>li,.stylish-side-nav .collapsible>li{padding:0}.btn-mdb{background-color:#45526E}.btn-mdb:hover{background-color:#4f5e7e!important}.btn-mdb.active,.btn-mdb:active,.btn-mdb:focus{background-color:#282f3f!important}.btn-mdb.dropdown-toggle{background-color:#45526E!important}.btn-mdb.dropdown-toggle:focus,.btn-mdb.dropdown-toggle:hover{background-color:#4f5e7e!important}.colorful-side-nav,.colorful-side-nav li{background-color:#00695c}.colorful-side-nav .collapsible a.active,.colorful-side-nav .collapsible a:active,.colorful-side-nav li.active,.colorful-side-nav li:hover{background-color:#008372}.colorful-side-nav .social{border-top:1px solid #26a69a;border-bottom:1px solid #26a69a}.stylish-side-nav,.stylish-side-nav li{background-color:#3E4551}.stylish-side-nav .collapsible a.active,.stylish-side-nav .collapsible a:active,.stylish-side-nav li.active,.stylish-side-nav li:hover{background-color:#4B515D}.stylish-side-nav .social{border-top:1px solid #4B515D;border-bottom:1px solid #4B515D}.light-side-nav .logo-wrapper,.light-side-nav .logo-wrapper a{height:80px}.light-side-nav .logo-wrapper img{padding:7% 50px}.light-side-nav .collapsible a,.light-side-nav p{color:#1C2331}.light-side-nav .social{border-top:1px solid #eee;border-bottom:1px solid #eee}.light-side-nav .navbar-form{margin:10px}.dark-side-nav,.dark-side-nav li{background-color:#212121}.dark-side-nav .collapsible a .active,.dark-side-nav .collapsible a:active,.dark-side-nav li.active,.dark-side-nav li:hover{background-color:#2E2E2E}.dark-side-nav .collapsible a{margin:0}.dark-side-nav .collapsible>li{padding:0}.dark-side-nav .social{border-top:1px solid #4B515D;border-bottom:1px solid #4B515D}.social-list{width:auto;padding:1rem;list-style-type:none}.social-list li{margin-top:15px}.social-list .fa{margin-right:20px;font-size:20px}.social-list .fa-facebook{margin-right:26px}.social-list a{font-size:20px}.btn-flat{padding:8px 30px;border:none;text-decoration:none;outline:0!important}.btn.btn-flat{color:inherit!important;background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-floating,.btn-floating i{display:inline-block;color:#fff}.btn-floating{z-index:1;overflow:hidden;width:47px;height:47px;padding:0;border-radius:50%;background-color:#a6c;-webkit-transition:.3s;transition:.3s}.btn-floating i{width:inherit;font-size:1.25rem;line-height:47px;text-align:center}.btn-floating:before{border-radius:0}.btn-floating.btn-sm,.btn-floating.btn-small,.btn-floating.wishlist{width:36.15px;height:36.15px}.btn-floating.btn-sm i,.btn-floating.btn-small i,.btn-floating.wishlist i{font-size:.96154rem;line-height:36.15px}.btn-floating.btn-large,.btn-floating.btn-lg{width:61.1px;height:61.1px}.btn-floating.btn-large i,.btn-floating.btn-lg i{font-size:1.625rem;line-height:61.1px}.fixed-action-btn{position:fixed;z-index:998;right:35px;bottom:35px;padding-top:15px;margin-bottom:0}.fixed-action-btn ul{position:absolute;right:0;bottom:64px;left:0;margin:0;padding:0;list-style-type:none;text-align:center}.fixed-action-btn ul li{margin-bottom:15px}.fixed-action-btn ul a.btn-floating{opacity:0}.btn-rounded{border-radius:10em}.btn.purple-gradient{background:-webkit-linear-gradient(50deg,#ff6ec4,#7873f5)!important;background:linear-gradient(40deg,#ff6ec4,#7873f5)!important;-webkit-transition:.5s ease;transition:.5s ease}.btn.purple-gradient:active,.btn.purple-gradient:active:focus .btn.purple-gradient.active,.btn.purple-gradient:focus,.btn.purple-gradient:hover{background:-webkit-linear-gradient(50deg,#ff88ce,#8f8bf7);background:linear-gradient(40deg,#ff88ce,#8f8bf7)}.btn.peach-gradient{background:-webkit-linear-gradient(50deg,#FFD86F,#FC6262)!important;background:linear-gradient(40deg,#FFD86F,#FC6262)!important;-webkit-transition:.5s ease;transition:.5s ease}.btn.peach-gradient:active,.btn.peach-gradient:active:focus .btn.peach-gradient.active,.btn.peach-gradient:focus,.btn.peach-gradient:hover{background:-webkit-linear-gradient(50deg,#ffdf89,#fc7b7b);background:linear-gradient(40deg,#ffdf89,#fc7b7b)}.btn.aqua-gradient{background:-webkit-linear-gradient(50deg,#2096ff,#05ffa3)!important;background:linear-gradient(40deg,#2096ff,#05ffa3)!important;-webkit-transition:.5s ease;transition:.5s ease}.btn.aqua-gradient:active,.btn.aqua-gradient:active:focus .btn.aqua-gradient.active,.btn.aqua-gradient:focus,.btn.aqua-gradient:hover{background:-webkit-linear-gradient(50deg,#3aa2ff,#1fffac);background:linear-gradient(40deg,#3aa2ff,#1fffac)}.btn.blue-gradient{background:-webkit-linear-gradient(50deg,#45cafc,#303f9f)!important;background:linear-gradient(40deg,#45cafc,#303f9f)!important;-webkit-transition:.5s ease;transition:.5s ease}.btn.blue-gradient:active,.btn.blue-gradient:active:focus .btn.blue-gradient.active,.btn.blue-gradient:focus,.btn.blue-gradient:hover{background:-webkit-linear-gradient(50deg,#5ed1fc,#3647b3);background:linear-gradient(40deg,#5ed1fc,#3647b3)}.btn-fb{background-color:#3B5998}.btn-fb:focus,.btn-fb:hover{background-color:#4264aa}.fb-ic{color:#3B5998!important}.fb-ic:focus,.fb-ic:hover{color:#3B5998}.btn-tw{background-color:#55ACEE}.btn-tw:focus,.btn-tw:hover{background-color:#6cb7f0}.tw-ic{color:#55ACEE!important}.tw-ic:focus,.tw-ic:hover{color:#55ACEE}.btn-gplus{background-color:#DD4B39}.btn-gplus:focus,.btn-gplus:hover{background-color:#e15f4f}.gplus-ic{color:#DD4B39!important}.gplus-ic:focus,.gplus-ic:hover{color:#DD4B39}.btn-yt{background-color:#ED302F}.btn-yt:focus,.btn-yt:hover{background-color:#ef4746}.yt-ic{color:#ED302F!important}.yt-ic:focus,.yt-ic:hover{color:#ED302F}.btn-li{background-color:#0082CA}.btn-li:focus,.btn-li:hover{background-color:#0092e4}.li-ic{color:#0082CA!important}.li-ic:focus,.li-ic:hover{color:#0082CA}.btn-pin{background-color:#C61118}.btn-pin:focus,.btn-pin:hover{background-color:#dd131b}.pin-ic{color:#C61118!important}.pin-ic:focus,.pin-ic:hover{color:#C61118}.btn-ins{background-color:#2E5E86}.btn-ins:focus,.btn-ins:hover{background-color:#356b99}.ins-ic{color:#2E5E86!important}.ins-ic:focus,.ins-ic:hover{color:#2E5E86}.btn-git{background-color:#333}.btn-git:focus,.btn-git:hover{background-color:#404040}.git-ic{color:#333!important}.git-ic:focus,.git-ic:hover{color:#333}.btn-comm{background-color:#30CFC0}.btn-comm:focus,.btn-comm:hover{background-color:#45d4c6}.comm-ic{color:#30CFC0!important}.comm-ic:focus,.comm-ic:hover{color:#30CFC0}.btn-vk{background-color:#4C75A3}.btn-vk:focus,.btn-vk:hover{background-color:#5882b1}.vk-ic{color:#4C75A3!important}.vk-ic:focus,.vk-ic:hover{color:#4C75A3}.btn-dribbble{background-color:#EC4A89}.btn-dribbble:focus,.btn-dribbble:hover{background-color:#ee6198}.dribbble-ic{color:#EC4A89!important}.dribbble-ic:focus,.dribbble-ic:hover{color:#EC4A89}.btn-so{background-color:#ffac44}.btn-so:focus,.btn-so:hover{background-color:#ffb75e}.so-ic{color:#ffac44!important}.so-ic:focus,.so-ic:hover{color:#ffac44}.btn-slack{background-color:#56b68b}.btn-slack:focus,.btn-slack:hover{background-color:#68be97}.slack-ic{color:#56b68b!important}.slack-ic:focus,.slack-ic:hover{color:#56b68b}.btn-email{background-color:#4B515D}.btn-email:focus,.btn-email:hover{background-color:#565d6b}.email-ic{color:#4B515D!important}.email-ic:focus,.email-ic:hover{color:#4B515D}.btn-social-all{background-color:#436281}.btn-social-all:focus,.btn-social-all:hover{background-color:#5c7fa3}.btn-social-all i.fa{margin-top:0}.counter{position:absolute;margin-left:-23px;margin-top:-1px;background-color:#fe1212;color:#fff;padding:1px 7px;font-size:11px;z-index:2;border-radius:10rem}.social-counters .btn{margin-left:9px}.icons-sm{padding:.5rem;margin:.5rem;font-size:1.2rem}.nav-tabs{border:0;padding:.7rem;margin-left:1rem;margin-right:1rem;margin-bottom:-20px;background-color:#2BBBAD;z-index:2;position:relative;border-radius:2px}.nav-tabs .nav-item+.nav-item{margin-left:0}.nav-tabs .nav-link{border:0;color:#fff}.nav-tabs .nav-item.open .nav-link,.nav-tabs .nav-link.active{background-color:rgba(255,255,255,.2);color:#fff;-webkit-transition:all 1s;transition:all 1s;border-radius:2px}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.dropdown-toggle{background-color:#2BBBAD;color:#fff;-webkit-transition:all 1s;transition:all 1s;border-radius:2px}.md-pills{border:0}.md-pills li{padding:.6rem}.md-pills .nav-link{-webkit-transition:all .4s;transition:all .4s;border-radius:2px;color:#666;text-align:center}.md-pills .nav-link:hover{background-color:rgba(158,158,158,.3)}.md-pills .nav-link.active{color:#fff;background-color:#2BBBAD}.pills-primary .nav-item .nav-link.active,.tabs-primary{background-color:#4285F4}.pills-danger .nav-item .nav-link.active,.tabs-danger{background-color:#ff3547}.pills-warning .nav-item .nav-link.active,.tabs-warning{background-color:#F80}.pills-success .nav-item .nav-link.active,.tabs-success{background-color:#00C851}.pills-info .nav-item .nav-link.active,.tabs-info{background-color:#33b5e5}.pills-default .nav-item .nav-link.active,.tabs-default{background-color:#2BBBAD}.pills-secondary .nav-item .nav-link.active,.tabs-secondary{background-color:#a6c}.pills-elegant .nav-item .nav-link.active,.tabs-elegant{background-color:#2E2E2E}.pills-unique .nav-item .nav-link.active,.tabs-unique{background-color:#880e4f}.pills-dark-green .nav-item .nav-link.active,.tabs-dark-green{background-color:#388E3C}.pills-mdb-color .nav-item .nav-link.active,.tabs-mdb-color{background-color:#59698D}.pills-red .nav-item .nav-link.active,.tabs-red{background-color:#D32F2F}.pills-pink .nav-item .nav-link.active,.tabs-pink{background-color:#ec407a}.pills-purple .nav-item .nav-link.active,.tabs-purple{background-color:#8e24aa}.pills-deep-purple .nav-item .nav-link.active,.tabs-deep-purple{background-color:#512da8}.pills-indigo .nav-item .nav-link.active,.tabs-indigo{background-color:#3f51b5}.pills-blue .nav-item .nav-link.active,.tabs-blue{background-color:#1976D2}.pills-light-blue .nav-item .nav-link.active,.tabs-light-blue{background-color:#82B1FF}.pills-cyan .nav-item .nav-link.active,.tabs-cyan{background-color:#00bcd4}.pills-teal .nav-item .nav-link.active,.tabs-teal{background-color:#00796b}.pills-green .nav-item .nav-link.active,.tabs-green{background-color:#388E3C}.pills-light-green .nav-item .nav-link.active,.tabs-light-green{background-color:#8bc34a}.pills-lime .nav-item .nav-link.active,.tabs-lime{background-color:#afb42b}.pills-yellow .nav-item .nav-link.active,.tabs-yellow{background-color:#fbc02d}.pills-amber .nav-item .nav-link.active,.tabs-amber{background-color:#ffa000}.pills-orange .nav-item .nav-link.active,.tabs-orange{background-color:#f57c00}.pills-deep-orange .nav-item .nav-link.active,.tabs-deep-orange{background-color:#ff7043}.pills-brown .nav-item .nav-link.active,.tabs-brown{background-color:#795548}.pills-grey .nav-item .nav-link.active,.tabs-grey{background-color:#616161}.pills-blue-grey .nav-item .nav-link.active,.tabs-blue-grey{background-color:#78909c}.pills-white .nav-item .nav-link.active,.tabs-white{background-color:#fff}.pills-black .nav-item .nav-link.active,.tabs-black{background-color:#000}.tab-content{padding:2rem 1rem 1rem;z-index:1;border-radius:0 0 .3rem .3rem}.tab-content.vertical{padding-top:0}.classic-tabs{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;white-space:nowrap;overflow-x:auto;border-radius:.3rem .3rem 0 0}@media (min-width:62rem){.classic-tabs{overflow-x:hidden}}.classic-tabs li{-webkit-box-flex:1 0 30%;-webkit-flex:1 0 30%;-ms-flex:1 0 30%;flex:1 0 30%}.classic-tabs li a{display:block;padding:20px 24px;font-size:13px;color:rgba(255,255,255,.7);text-align:center;border-radius:0}.card .card-data ul li,.card .card-review ul li{display:inline}.classic-tabs li a.active{border-bottom:3px solid;color:#fff}@media (min-width:62em){.classic-tabs li{-webkit-box-flex:inherit;-webkit-flex:inherit;-ms-flex:inherit;flex:inherit}.classic-tabs li:first-child{margin-left:56px}}.classic-tabs.tabs-cyan li a.active{border-color:#ffeb3b}.classic-tabs.tabs-orange li a.active{border-color:#E53935}.classic-tabs.tabs-grey li a.active{border-color:#FFF}.classic-tabs.tabs-pink li a.active{border-color:#673ab7}.classic-tabs.tabs-green li a.active{border-color:#1565C0}.classic-tabs.tabs-primary li a.active{border-color:#FFF}.card.card-image{background-size:cover;background-position:center;width:100%}.card .card-data{background-color:#929FBA;color:#fff;text-align:center;height:auto;padding:10px}.card .card-data ul{margin-bottom:0;font-size:.9rem}.card .card-data ul li .fa-clock-o{margin-left:10px}.card .card-data ul a{color:#fff}.card .card-data ul a .fa{margin-left:5px;margin-right:3px}.card.card-dark .card-body{background-color:#2E2E2E}.card.card-dark .card-body hr{background-color:#666}.card.card-cascade{width:100%}.card.card-cascade .view{border-radius:4px}.card.card-cascade .view.gradient-card-header{padding:1.6rem 1rem;text-align:center}.card.card-cascade .view.gradient-card-header .btn-floating{background-color:rgba(255,255,255,.2)}.card.card-cascade.narrower{margin-top:20px}.card.card-cascade.narrower .view{margin-left:4%;margin-right:4%;margin-top:-20px}.card.card-cascade.wider{background-color:transparent}.card.card-cascade.wider .view{z-index:2}.card.card-cascade.wider .card-body{margin-left:4%;margin-right:4%;background:#fff;z-index:1;border-radius:0 0 .3rem .3rem}.card.card-cascade.wider.reverse .card-body{z-index:3;margin-top:-1rem;border-radius:4px}.card.card-cascade.card-avatar{margin-top:6rem;text-align:center}.card.card-cascade.card-avatar img{margin-top:-5rem;margin-left:auto;margin-right:auto;width:160px;border-radius:50%}.card.card-cascade .card-body{padding-top:1.8rem}.card.card-cascade.panel-cascade .view{text-align:center;color:#fff}.card.card-cascade.panel-cascade .list-group .list-group-item{margin-bottom:0;border:0;border-bottom:1px solid #eee;color:#495057}.card.card-cascade.panel-cascade .list-group .list-group-item:hover{background-color:#eee}.card .activator{position:absolute;top:0;right:0;padding:1rem;margin-right:10px;font-size:1.2rem}.card .rating{color:#ffa000}.card .btn-action{margin:-23px 20px -23px auto;background-color:#929FBA;height:47px;width:47px;line-height:0}.card .btn-action .fa{font-size:18px}.card .btn-action .fa.fa-chevron-right{margin-top:2px;margin-left:2px}.card .card-review{margin-top:-1px;color:#fff;padding:50px 20px 20px}.card .card-review ul{margin-bottom:0;font-size:.9rem}.card .card-review ul a{color:#fff}.card .card-review ul a .fa{margin-left:5px;margin-right:3px}.card .card-reveal{position:absolute;width:100%;overflow-y:auto;top:100%;height:100%;z-index:1;display:none;padding:1rem}.card .card-reveal .card-title i{color:#9e9e9e;position:absolute;right:10px}.card .card-reveal .content,.card .card-share{position:relative}.card .card-reveal .content h4{margin-top:20px;margin-bottom:15px}.card .card-reveal .content h5{margin-top:30px}.card .card-share .social-reveal{position:absolute;top:-28px;right:30px;visibility:hidden;width:auto;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0);-webkit-transition:-webkit-transform .35s ease;transition:-webkit-transform .35s ease;transition:transform .35s ease;transition:transform .35s ease,-webkit-transform .35s ease}.card .card-share .social-reveal .btn-floating{margin:.3rem}.card .card-share .social-reveal .btn-floating i{font-size:18px}.card .card-share .social-reveal-active{z-index:11;visibility:visible;-webkit-transform:translateZ(0);transform:translateZ(0);-webkit-transform:translateX(-48px);-ms-transform:translateX(-48px);transform:translateX(-48px);-webkit-transition:-webkit-transform .35s ease;transition:-webkit-transform .35s ease;transition:transform .35s ease;transition:transform .35s ease,-webkit-transform .35s ease}.pswp--touch .pswp__button--arrow--left,.pswp--touch .pswp__button--arrow--right,.pswp__caption--fake{visibility:hidden}.card.ovf-hidden{overflow:hidden}.card .card-footer{background-color:transparent}.card .card-footer .left{float:left}.card .card-footer .left .discount{text-decoration:line-through;color:#9e9e9e;font-size:1.1rem}.card .card-footer .right{float:right;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.card .card-footer .right a{color:#757575;margin-left:1rem;-webkit-transition:.4s;transition:.4s}.card .card-footer .right a:hover{color:#d50000;-webkit-transition:.4s;transition:.4s}.card .card-footer .right a.active{color:#d50000}.card-wrapper{margin:0;min-height:500px;position:relative;-webkit-perspective:800px;perspective:800px}.card-wrapper .face{position:absolute;width:100%;height:100%}.card-wrapper .face h4{margin-bottom:15px}.card-wrapper .face h5{margin-top:30px}.card-wrapper .face .content{text-align:left;padding:15px}.card-wrapper .face .content p{margin-bottom:30px}.card-wrapper .face .content .rotate-btn{padding:1rem;margin-right:-8px;float:right;font-size:1.2rem}.card-wrapper .card-up{overflow:hidden;height:50%}.card-wrapper .card-up img{min-width:400px}.card-wrapper .avatar{border-radius:50%;display:block;height:120px;margin:-65px auto 0;overflow:hidden;width:120px}.card-wrapper .avatar img{border:5px solid #fff;background:#FFF;width:100%}.card-wrapper .card-rotating{text-align:center;position:absolute;width:100%;height:100%;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.card-wrapper .card-rotating .content{position:relative}.card-wrapper .card-rotating .content .rotate-btn{position:absolute;right:8px;top:0}.card-wrapper .fa-repeat,.card-wrapper .fa-undo{font-size:20px;margin-top:30px}.card-wrapper .fa-undo{margin-top:30px}.card-wrapper .back,.card-wrapper .front{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition:-webkit-transform 1s;transition:-webkit-transform 1s;transition:transform 1s;transition:transform 1s,-webkit-transform 1s}.pswp,.pswp--has_mouse .pswp__button--arrow--left,.pswp--has_mouse .pswp__button--arrow--right,.pswp__bg,.pswp__caption,.pswp__container,.pswp__img--placeholder,.pswp__share-tooltip,.pswp__top-bar,.pswp__zoom-wrap,.side-nav,[type=checkbox]:checked+label:before,[type=checkbox]:indeterminate+label:before{-webkit-backface-visibility:hidden}.card-wrapper .back{-webkit-transform:rotateY(-180deg);transform:rotateY(-180deg);padding:1rem}.card-wrapper .back .card-title i{color:#9e9e9e;position:absolute;right:20px}.card-wrapper .card-rotating.effect__click.flipped .front{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}.card-wrapper .card-rotating.effect__click.flipped .back{-webkit-transform:rotateY(0);transform:rotateY(0)}.testimonial-card .card-up{overflow:hidden;height:120px;border-radius:.3rem .3rem 0 0}.testimonial-card .avatar{border-radius:50%;height:120px;width:120px;margin:-65px auto 0;overflow:hidden;border:5px solid #fff}.testimonial-card .avatar img{width:100%}.testimonial-card .card-body{text-align:center}.card-inverse h5{font-size:1rem}.card-overlay{background-size:cover;padding:1.5rem;border-radius:2px}.card-overlay p{margin-bottom:1rem}.dropdown .dropdown-menu{padding:.5rem}.dropdown .dropdown-menu.dropdown-primary .dropdown-item:active,.dropdown .dropdown-menu.dropdown-primary .dropdown-item:hover{background-color:#4285F4}.dropdown .dropdown-menu.dropdown-danger .dropdown-item:active,.dropdown .dropdown-menu.dropdown-danger .dropdown-item:hover{background-color:#C00}.dropdown .dropdown-menu.dropdown-default .dropdown-item:active,.dropdown .dropdown-menu.dropdown-default .dropdown-item:hover{background-color:#2BBBAD}.dropdown .dropdown-menu.dropdown-secondary .dropdown-item:active,.dropdown .dropdown-menu.dropdown-secondary .dropdown-item:hover{background-color:#a6c}.dropdown .dropdown-menu.dropdown-success .dropdown-item:active,.dropdown .dropdown-menu.dropdown-success .dropdown-item:hover{background-color:#00C851}.dropdown .dropdown-menu.dropdown-info .dropdown-item:active,.dropdown .dropdown-menu.dropdown-info .dropdown-item:hover{background-color:#33b5e5}.dropdown .dropdown-menu.dropdown-warning .dropdown-item:active,.dropdown .dropdown-menu.dropdown-warning .dropdown-item:hover{background-color:#fb3}.dropdown .dropdown-menu.dropdown-dark .dropdown-item:active,.dropdown .dropdown-menu.dropdown-dark .dropdown-item:hover{background-color:#2E2E2E}.dropdown .dropdown-menu.dropdown-ins .dropdown-item:active,.dropdown .dropdown-menu.dropdown-ins .dropdown-item:hover{background-color:#2E5E86}.dropdown .dropdown-menu .dropdown-item{padding:.5rem;margin-left:0;font-size:.9rem}.dropdown .dropdown-menu .dropdown-item.disabled{color:#868e96}.dropdown .dropdown-menu .dropdown-item.disabled:active,.dropdown .dropdown-menu .dropdown-item.disabled:focus,.dropdown .dropdown-menu .dropdown-item.disabled:hover{-webkit-box-shadow:none;box-shadow:none;color:#868e96!important;background-color:transparent!important}.dropdown .dropdown-menu .dropdown-item:active,.dropdown .dropdown-menu .dropdown-item:hover{border-radius:2px;-webkit-transition:all .1s linear;transition:all .1s linear;background-color:#4285F4}.dropdown-content{background-color:#fff;margin:0;display:none;min-width:100px;max-height:650px;overflow-y:auto;opacity:0;position:absolute;z-index:999;will-change:width,height}.dropdown-content li{clear:both;color:#000;cursor:pointer;line-height:1.3rem;width:100%;text-align:left;text-transform:none}.dropdown-content li.active,.dropdown-content li:hover{background-color:#eee}.dropdown-content li>a,.dropdown-content li>span{font-size:.9rem;color:#4285F4;display:block;padding:.5rem}.dropdown-content li>a>i{height:inherit;line-height:inherit}.colorful-select .dropdown-content{padding:.5rem}.navbar .nav-item.avatar,.navbar .nav-item.avatar .dropdown-toggle{padding:0}.colorful-select .dropdown-content li.active span{color:#fff!important}.colorful-select .dropdown-content li.active span [type=checkbox]:checked+label:before{border-color:transparent #fff #fff transparent}.colorful-select .dropdown-content li a:hover,.colorful-select .dropdown-content li span:hover{color:#fff!important;-webkit-transition:all .1s linear;transition:all .1s linear;border-radius:2px}.colorful-select .dropdown-content li a:hover [type=checkbox]+label:before,.colorful-select .dropdown-content li span:hover [type=checkbox]+label:before{border-color:#fff}.colorful-select .dropdown-content li a:hover [type=checkbox]:checked+label:before,.colorful-select .dropdown-content li span:hover [type=checkbox]:checked+label:before{border-color:transparent #fff #fff transparent}.colorful-select .dropdown-content li.disabled.active span,.colorful-select .dropdown-content li.optgroup.active span,.colorful-select .dropdown-content li:disabled.active span{color:rgba(0,0,0,.3)!important;border-bottom-color:rgba(0,0,0,.3);cursor:default}.colorful-select .dropdown-content li.disabled a:hover,.colorful-select .dropdown-content li.disabled span:hover,.colorful-select .dropdown-content li.optgroup a:hover,.colorful-select .dropdown-content li.optgroup span:hover,.colorful-select .dropdown-content li:disabled a:hover,.colorful-select .dropdown-content li:disabled span:hover{color:rgba(0,0,0,.3)!important;border-bottom-color:rgba(0,0,0,.3);cursor:default;background-color:#fff!important}.colorful-select .dropdown-content li.disabled label,.colorful-select .dropdown-content li.optgroup label,.colorful-select .dropdown-content li:disabled label{cursor:default}.dropdown-primary .dropdown-content li a,.dropdown-primary .dropdown-content li span:hover,.dropdown-primary .dropdown-content li.active{background-color:#4285F4}.dropdown-primary .search-wrap input:focus{border-bottom:1px solid #4285F4;-webkit-box-shadow:0 1px 0 0 #4285F4;box-shadow:0 1px 0 0 #4285F4}.dropdown-danger .dropdown-content li a,.dropdown-danger .dropdown-content li span:hover,.dropdown-danger .dropdown-content li.active{background-color:#C00}.dropdown-danger .search-wrap input:focus{border-bottom:1px solid #C00;-webkit-box-shadow:0 1px 0 0 #C00;box-shadow:0 1px 0 0 #C00}.dropdown-default .dropdown-content li a,.dropdown-default .dropdown-content li span:hover,.dropdown-default .dropdown-content li.active{background-color:#2BBBAD}.dropdown-default .search-wrap input:focus{border-bottom:1px solid #2BBBAD;-webkit-box-shadow:0 1px 0 0 #2BBBAD;box-shadow:0 1px 0 0 #2BBBAD}.dropdown-secondary .dropdown-content li a,.dropdown-secondary .dropdown-content li span:hover,.dropdown-secondary .dropdown-content li.active{background-color:#a6c}.dropdown-secondary .search-wrap input:focus{border-bottom:1px solid #a6c;-webkit-box-shadow:0 1px 0 0 #a6c;box-shadow:0 1px 0 0 #a6c}.dropdown-success .dropdown-content li a,.dropdown-success .dropdown-content li span:hover,.dropdown-success .dropdown-content li.active{background-color:#00C851}.dropdown-success .search-wrap input:focus{border-bottom:1px solid #00C851;-webkit-box-shadow:0 1px 0 0 #00C851;box-shadow:0 1px 0 0 #00C851}.dropdown-info .dropdown-content li a,.dropdown-info .dropdown-content li span:hover,.dropdown-info .dropdown-content li.active{background-color:#33b5e5}.dropdown-info .search-wrap input:focus{border-bottom:1px solid #33b5e5;-webkit-box-shadow:0 1px 0 0 #33b5e5;box-shadow:0 1px 0 0 #33b5e5}.dropdown-warning .dropdown-content li a,.dropdown-warning .dropdown-content li span:hover,.dropdown-warning .dropdown-content li.active{background-color:#fb3}.dropdown-warning .search-wrap input:focus{border-bottom:1px solid #fb3;-webkit-box-shadow:0 1px 0 0 #fb3;box-shadow:0 1px 0 0 #fb3}.dropdown-dark .dropdown-content li a,.dropdown-dark .dropdown-content li span:hover,.dropdown-dark .dropdown-content li.active{background-color:#2E2E2E}.dropdown-dark .search-wrap input:focus{border-bottom:1px solid #2E2E2E;-webkit-box-shadow:0 1px 0 0 #2E2E2E;box-shadow:0 1px 0 0 #2E2E2E}.dropdown-ins .dropdown-content li a,.dropdown-ins .dropdown-content li span:hover,.dropdown-ins .dropdown-content li.active{background-color:#2E5E86}.dropdown-ins .search-wrap input:focus{border-bottom:1px solid #2E5E86;-webkit-box-shadow:0 1px 0 0 #2E5E86;box-shadow:0 1px 0 0 #2E5E86}.dropdown-menu.animated{-webkit-animation-duration:.55s;animation-duration:.55s;-webkit-animation-timing-function:ease;animation-timing-function:ease}.navbar .nav-item.avatar.active{background-color:transparent!important}.nav-pills .nav-item a.active,.nav-pills .nav-item a.active:active,.nav-pills .nav-item a.active:focus,.nav-pills .nav-item a.active:hover,.nav-pills .nav-item a:hover{background-color:transparent;font-weight:500}.navbar .nav-item.avatar .dropdown-toggle img{height:35px}.navbar .nav-item.avatar .dropdown-toggle:after{display:none}.double-nav{z-index:100;color:#fff}@media (max-width:992px){.double-nav{padding-top:4px;padding-bottom:4px}}@media (max-width:768px){.double-nav .container{padding-left:0;padding-right:0}}.double-nav a{color:#fff;font-size:15px}.double-nav .breadcrumb-dn p{margin:0;padding-top:0;padding-left:1rem}@media (max-width:993px){.double-nav .breadcrumb-dn{display:none}}.double-nav .button-collapse{position:absolute;left:10px;font-size:1.5rem}@media (min-width:1440px){.double-nav .button-collapse{display:none}}@media (max-width:1440px){.double-nav .button-collapse{display:block;position:relative;font-size:1.4rem;margin-right:10px;margin-left:10px}}.nav-pills .nav-item a{text-align:left;color:#666;border-radius:0}.nav-pills .nav-item a:hover{border-left:1px solid}.nav-pills .nav-item a.active{color:#45526E;border-left:2px solid;-webkit-box-shadow:none;box-shadow:none}.nav-pills .nav-item+.nav-item{margin-left:0}@media only screen and (max-width:991px){.sticky,.sticky-placeholder{display:none}}@media only screen and (max-width:992px){.col-lg-4 .sticky,.col-md-4 .sticky,.col-xl-4 .sticky{width:200px}}@media only screen and (min-width:992px){.col-md-4 .sticky .col-lg-4 .sticky,.col-xl-4 .sticky{width:400px}}@media only screen and (min-width:1200px){.col-md-4 .sticky{width:300px}}@media only screen and (min-width:1440px){.col-md-4 .sticky{width:350px}}.dotted-scrollspy{display:block;position:fixed;top:50%;right:0;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);background:rgba(0,0,0,.55);border-radius:2px 0 0 2px}.dotted-scrollspy li{display:block;padding:0 16px}.dotted-scrollspy li:first-child{padding-top:10px}.dotted-scrollspy li:last-child{padding-bottom:10px}.dotted-scrollspy li a{padding:.5rem}.dotted-scrollspy li a span{display:block;background-color:rgba(255,255,255,.54);width:8px;height:8px;border-radius:50%}.dotted-scrollspy li a.active span{background:#fff}.scrollspy-example{overflow-y:scroll;position:relative;height:200px;padding:1rem}.pswp,.pswp__item,.pswp__scroll-wrap{overflow:hidden}.pswp,.pswp__bg,.pswp__scroll-wrap{width:100%;height:100%;top:0;position:absolute;left:0}.pswp{display:none;-ms-touch-action:none;touch-action:none;z-index:1500;outline:0}.pswp--open,.pswp__button{display:block}.pswp *{-webkit-box-sizing:border-box;box-sizing:border-box}.pswp img{max-width:none}.pswp--animate_opacity{opacity:.001;will-change:opacity;-webkit-transition:opacity 333ms cubic-bezier(.4,0,.22,1);transition:opacity 333ms cubic-bezier(.4,0,.22,1)}.pswp--zoom-allowed .pswp__img{cursor:-webkit-zoom-in;cursor:-moz-zoom-in;cursor:zoom-in}.pswp--zoomed-in .pswp__img{cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.pswp--dragging .pswp__img{cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.pswp__container,.pswp__zoom-wrap{-ms-touch-action:none;touch-action:none;position:absolute;left:0;right:0;top:0;bottom:0}.pswp__container,.pswp__img{user-select:none;-webkit-touch-callout:none}.pswp__zoom-wrap{position:absolute;width:100%;-webkit-transform-origin:left top;-ms-transform-origin:left top;transform-origin:left top;-webkit-transition:-webkit-transform 333ms cubic-bezier(.4,0,.22,1);transition:-webkit-transform 333ms cubic-bezier(.4,0,.22,1);transition:transform 333ms cubic-bezier(.4,0,.22,1);transition:transform 333ms cubic-bezier(.4,0,.22,1),-webkit-transform 333ms cubic-bezier(.4,0,.22,1)}.pswp__bg{background:#000;opacity:0;will-change:opacity;-webkit-transition:opacity 333ms cubic-bezier(.4,0,.22,1);transition:opacity 333ms cubic-bezier(.4,0,.22,1)}.pswp--animated-in .pswp__bg,.pswp--animated-in .pswp__zoom-wrap{-webkit-transition:none;transition:none}.pswp__item{position:absolute;left:0;right:0;top:0;bottom:0}.pswp__img{position:absolute;width:auto;height:auto;top:0;left:0}.pswp__img--placeholder--blank{background:#222}.pswp--ie .pswp__img{width:100%!important;height:auto!important;left:0;top:0}.pswp__error-msg{position:absolute;left:0;top:50%;width:100%;text-align:center;font-size:14px;line-height:16px;margin-top:-8px;color:#CCC}.pswp__error-msg a{color:#CCC;text-decoration:underline}.pswp__share-tooltip a,.pswp__share-tooltip a:hover{text-decoration:none;color:#000}.pswp__button{position:relative;cursor:pointer;overflow:visible;border:0;padding:0;margin:0;float:right;opacity:.75;-webkit-transition:opacity .2s;transition:opacity .2s;-webkit-box-shadow:none;box-shadow:none}.mdb-autocomplete-wrap,.pswp__share-tooltip{-webkit-box-shadow:0 2px 5px rgba(0,0,0,.25)}.pswp__button:focus,.pswp__button:hover{opacity:1}.pswp__button:active{outline:0;opacity:.9}.pswp__button::-moz-focus-inner{padding:0;border:0}.pswp__ui--over-close .pswp__button--close{opacity:1}.pswp__button,.pswp__button--arrow--left:before,.pswp__button--arrow--right:before{background:url(../img/lightbox/default-skin.png) no-repeat;background-size:264px 88px;width:44px;height:44px}@media (-webkit-min-device-pixel-ratio:1.1),(-webkit-min-device-pixel-ratio:1.09375),(min-resolution:105dpi),(min-resolution:1.1dppx){.pswp--svg .pswp__button,.pswp--svg .pswp__button--arrow--left:before,.pswp--svg .pswp__button--arrow--right:before{background-image:url(../img/lightbox/default-skin.svg)}.pswp--svg .pswp__button--arrow--left,.pswp--svg .pswp__button--arrow--right{background:0 0}}.pswp__button--close{background-position:0 -44px}.pswp__button--share{background-position:-44px -44px}.pswp__button--fs{display:none}.pswp--supports-fs .pswp__button--fs{display:block}.pswp--fs .pswp__button--fs{background-position:-44px 0}.pswp__button--zoom{display:none;background-position:-88px 0}.pswp--zoom-allowed .pswp__button--zoom{display:block}.pswp--zoomed-in .pswp__button--zoom{background-position:-132px 0}.pswp__button--arrow--left,.pswp__button--arrow--right{background:0 0;top:50%;margin-top:-50px;width:70px;height:100px;position:absolute}.pswp__button--arrow--left{left:0}.pswp__button--arrow--right{right:0}.pswp__button--arrow--left:before,.pswp__button--arrow--right:before{content:'';top:35px;background-color:rgba(0,0,0,.3);height:30px;width:32px;position:absolute}.pswp__button--arrow--left:before{left:6px;background-position:-138px -44px}.pswp__button--arrow--right:before{right:6px;background-position:-94px -44px}.pswp__counter,.pswp__share-modal{user-select:none}.pswp__share-modal{display:block;background:rgba(0,0,0,.5);width:100%;height:100%;top:0;left:0;padding:10px;position:absolute;z-index:1600;opacity:0;-webkit-transition:opacity .25s ease-out;transition:opacity .25s ease-out;-webkit-backface-visibility:hidden;will-change:opacity}.pswp__share-modal--hidden{display:none}.pswp__share-tooltip{z-index:1620;position:absolute;background:#FFF;top:56px;border-radius:2px;display:block;width:auto;right:44px;box-shadow:0 2px 5px rgba(0,0,0,.25);-webkit-transform:translateY(6px);-ms-transform:translateY(6px);transform:translateY(6px);-webkit-transition:-webkit-transform .25s;transition:-webkit-transform .25s;transition:transform .25s;transition:transform .25s,-webkit-transform .25s;will-change:transform}.chips,.progress{-webkit-box-shadow:none}.pswp__share-tooltip a{display:block;padding:8px 12px;font-size:14px;line-height:18px}.pswp__share-tooltip a:first-child{border-radius:2px 2px 0 0}.pswp__share-tooltip a:last-child{border-radius:0 0 2px 2px}.pswp__share-modal--fade-in{opacity:1}.pswp__share-modal--fade-in .pswp__share-tooltip{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.pswp--touch .pswp__share-tooltip a{padding:16px 12px}a.pswp__share--facebook:before{content:'';display:block;width:0;height:0;position:absolute;top:-12px;right:15px;border:6px solid transparent;border-bottom-color:#FFF;-webkit-pointer-events:none;-moz-pointer-events:none;pointer-events:none}.pswp__caption--empty,.pswp__ui--one-slide .pswp__button--arrow--left,.pswp__ui--one-slide .pswp__button--arrow--right,.pswp__ui--one-slide .pswp__counter{display:none}.pswp__counter,.pswp__preloader{height:44px;top:0;position:absolute}a.pswp__share--facebook:hover{background:#3E5C9A;color:#FFF}a.pswp__share--facebook:hover:before{border-bottom-color:#3E5C9A}a.pswp__share--twitter:hover{background:#55ACEE;color:#FFF}a.pswp__share--pinterest:hover{background:#CCC;color:#CE272D}a.pswp__share--download:hover{background:#DDD}.pswp__counter{left:0;font-size:13px;line-height:44px;color:#FFF;opacity:.75;padding:0 10px}.pswp__caption{position:absolute;left:0;bottom:0;width:100%;min-height:44px}.pswp__caption small{font-size:11px;color:#BBB}.pswp__caption__center{text-align:left;max-width:420px;margin:0 auto;font-size:13px;padding:10px;line-height:20px;color:#CCC}.carousel-multi-item .controls-top,.cart-modal .table,.cart-modal th,.comments-list h4,.product-panel .modal-header,.ql-modal .modal-header,.reply-form h4,.side-nav .about p,.side-nav .social,.stepper li a,.stepper li a .circle,input[type=range]+.thumb .value{text-align:center}.chip,.chip .close,.chips .input{line-height:32px}.pswp--has_mouse .pswp__button--arrow--left,.pswp--has_mouse .pswp__button--arrow--right,.pswp__ui{visibility:visible}.pswp__preloader{width:44px;left:50%;margin-left:-22px;opacity:0;-webkit-transition:opacity .25s ease-out;transition:opacity .25s ease-out;will-change:opacity;direction:ltr}.pswp--css_animation .pswp__preloader--active,.pswp__preloader--active{opacity:1}.pswp__preloader__icn{width:20px;height:20px;margin:12px}.pswp__preloader--active .pswp__preloader__icn{background:url(../img/lightbox/preloader.gif) no-repeat}.pswp--css_animation .pswp__preloader--active .pswp__preloader__icn{-webkit-animation:clockwise .5s linear infinite;animation:clockwise .5s linear infinite}.pswp--css_animation .pswp__preloader--active .pswp__preloader__donut{-webkit-animation:donut-rotate 1s cubic-bezier(.4,0,.22,1) infinite;animation:donut-rotate 1s cubic-bezier(.4,0,.22,1) infinite}.pswp--css_animation .pswp__preloader__icn{background:0 0;opacity:.75;width:14px;height:14px;position:absolute;left:15px;top:15px;margin:0}.pswp--css_animation .pswp__preloader__cut{position:relative;width:7px;height:14px;overflow:hidden}.pswp--css_animation .pswp__preloader__donut{-webkit-box-sizing:border-box;box-sizing:border-box;width:14px;height:14px;border:2px solid #FFF;border-radius:50%;border-left-color:transparent;border-bottom-color:transparent;position:absolute;top:0;left:0;background:0 0;margin:0}@media screen and (max-width:1024px){.pswp__preloader{position:relative;left:auto;top:auto;margin:0;float:right}}@-webkit-keyframes clockwise{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes clockwise{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes donut-rotate{0%,100%{-webkit-transform:rotate(0);transform:rotate(0)}50%{-webkit-transform:rotate(-140deg);transform:rotate(-140deg)}}@keyframes donut-rotate{0%,100%{-webkit-transform:rotate(0);transform:rotate(0)}50%{-webkit-transform:rotate(-140deg);transform:rotate(-140deg)}}.pswp__ui{-webkit-font-smoothing:auto;opacity:1;z-index:1550}.pswp__top-bar{position:absolute;left:0;top:0;height:44px;width:100%}.pswp--has_mouse .pswp__button--arrow--left,.pswp--has_mouse .pswp__button--arrow--right,.pswp__caption,.pswp__top-bar{will-change:opacity;-webkit-transition:opacity 333ms cubic-bezier(.4,0,.22,1);transition:opacity 333ms cubic-bezier(.4,0,.22,1)}.pswp__caption,.pswp__top-bar{background-color:rgba(0,0,0,.5)}.pswp__ui--fit .pswp__caption,.pswp__ui--fit .pswp__top-bar{background-color:rgba(0,0,0,.3)}.pswp__ui--idle .pswp__button--arrow--left,.pswp__ui--idle .pswp__button--arrow--right,.pswp__ui--idle .pswp__top-bar{opacity:0}.pswp__ui--hidden .pswp__button--arrow--left,.pswp__ui--hidden .pswp__button--arrow--right,.pswp__ui--hidden .pswp__caption,.pswp__ui--hidden .pswp__top-bar{opacity:.001}.pswp__element--disabled{display:none!important}.pswp--minimal--dark .pswp__top-bar{background:0 0}.mdb-lightbox figure{margin:0;float:left}.comments-list .mdb-lightbox figure img,.mdb-lightbox figure .comments-list img,.mdb-lightbox figure .img-fluid,.mdb-lightbox figure .modal-dialog.cascading-modal.modal-avatar .modal-header,.mdb-lightbox figure .reply-form img,.mdb-lightbox figure .section-blog-fw .view img,.modal-dialog.cascading-modal.modal-avatar .mdb-lightbox figure .modal-header,.reply-form .mdb-lightbox figure img,.section-blog-fw .view .mdb-lightbox figure img{display:inline}.chip,.chips .input{display:inline-block}.mdb-lightbox figure img{cursor:-webkit-zoom-in;cursor:zoom-in;-webkit-transition:opacity .4s;transition:opacity .4s;border-radius:0}.mdb-lightbox figure img:hover{opacity:.8}.mdb-lightbox.no-margin [class*=col-]{padding:0}.mdb-lightbox [class*=col-]{padding:.5rem}.chip{font-size:13px;color:rgba(0,0,0,.6);padding:0 12px;border-radius:16px;background-color:#eceff1;margin-bottom:1rem;margin-right:1rem}.chip img{float:left;margin:0 8px 0 -12px;height:32px;width:32px;border-radius:50%}.chip .close{cursor:pointer;float:right;font-size:16px;padding-left:8px;-webkit-transition:all .1s linear;transition:all .1s linear}.chips{outline:0;box-shadow:none;border:none;border-bottom:1px solid #bdbdbd;margin-bottom:30px;min-height:45px;padding-bottom:1rem;-webkit-transition:all .3s;transition:all .3s}.chips.focus{border-bottom:1px solid #4285F4;-webkit-box-shadow:0 1px 0 0 #4285F4;box-shadow:0 1px 0 0 #4285F4}.chips:hover{cursor:text}.chips .tag.selected{border-bottom:1px solid #4285F4;color:#fff}.chips .input{background:0 0;border:0;outline:0;padding:0!important;width:120px!important;color:rgba(0,0,0,.6);font-size:13px;margin-right:20px}.chips .input:focus{border:0!important;-webkit-box-shadow:none!important;box-shadow:none!important}.table a{margin-left:1rem}.table fieldset{margin-bottom:0}.table fieldset label{height:8px}.product-table img{max-height:150px;min-width:50px}[type=checkbox],[type=radio]{position:absolute;left:-9999px;visibility:hidden}[type=checkbox]+label,[type=radio]+label{position:relative;padding-left:35px;cursor:pointer;display:inline-block;height:25px;line-height:25px;font-size:1rem;-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}.streak{display:block;position:relative;overflow:hidden;height:250px}.streak.streak-md{height:400px}@media (max-width:736px){.streak.streak-md{height:300px}}.streak.streak-lg{height:650px}@media (max-width:450px){.streak.streak-lg{height:900px}}.streak.streak-long{height:200px}@media (max-width:450px){.streak.streak-long{height:620px}}.streak.streak-long-2{height:400px}@media (max-width:450px){.streak.streak-long-2{height:700px}}.streak.streak-photo{background-repeat:no-repeat;background-size:cover;background-position:center}@media (min-width:1366px){.streak.streak-photo{background-attachment:fixed}}.streak.no-flex{padding-top:3.125rem;padding-bottom:3.125rem;height:auto}.purple-gradient{background:-webkit-linear-gradient(50deg,#ff6ec4,#7873f5);background:linear-gradient(40deg,#ff6ec4,#7873f5)}.peach-gradient{background:-webkit-linear-gradient(50deg,#FFD86F,#FC6262);background:linear-gradient(40deg,#FFD86F,#FC6262)}.aqua-gradient{background:-webkit-linear-gradient(50deg,#2096ff,#05ffa3);background:linear-gradient(40deg,#2096ff,#05ffa3)}.blue-gradient{background:-webkit-linear-gradient(50deg,#45cafc,#303f9f);background:linear-gradient(40deg,#45cafc,#303f9f)}[type=radio]+label{-webkit-transition:.28s ease;transition:.28s ease}[type=radio]+label:after,[type=radio]+label:before{content:'';position:absolute;left:0;top:0;margin:4px;width:16px;height:16px;z-index:0;border-radius:50%;border-style:solid;border-width:2px;-webkit-transition:.28s ease;transition:.28s ease}[type=radio]:not(:checked)+label:after,[type=radio]:not(:checked)+label:before{border-color:#5a5a5a}[type=radio]:not(:checked)+label:after{z-index:-1;-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0)}[type=radio]:checked+label:before{border-color:transparent}[type=radio]:checked+label:after{border-color:#4285F4;background-color:#4285F4;z-index:0;-webkit-transform:scale(1.02);-ms-transform:scale(1.02);transform:scale(1.02)}[type=radio]:disabled+label{color:rgba(0,0,0,.46)}[type=radio]:disabled+label:before{background-color:transparent;border-color:rgba(0,0,0,.46)}[type=radio]:disabled:not(:checked)+label:before{border-color:rgba(0,0,0,.46)}[type=radio]:disabled:checked+label:after{background-color:rgba(0,0,0,.46);border-color:#BDBDBD}[type=radio].with-gap:checked+label:before{border-color:#4285F4}[type=radio].with-gap:checked+label:after{-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}[type=radio].with-gap:checked:disabled+label:before{border-color:rgba(0,0,0,.46)}[type=checkbox]+label:before{content:'';position:absolute;top:0;left:0;width:17px;height:17px;z-index:0;border:1.5px solid #8a8a8a;border-radius:1px;margin-top:2px;-webkit-transition:.2s;transition:.2s}[type=checkbox]:checked+label:before{top:-4px;left:-3px;width:12px;height:22px;border-style:solid;border-width:2px;border-color:transparent #4285F4 #4285F4 transparent;-webkit-transform:rotate(40deg);-ms-transform:rotate(40deg);transform:rotate(40deg);-webkit-transform-origin:100% 100%;-ms-transform-origin:100% 100%;transform-origin:100% 100%}[type=checkbox]:indeterminate+label:before{left:-10px;top:-11px;width:10px;height:22px;border:none;border-right:2px solid #4285F4;-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:100% 100%;-ms-transform-origin:100% 100%;transform-origin:100% 100%}[type=checkbox]:disabled:checked+label:before{border-color:transparent rgba(0,0,0,.46) rgba(0,0,0,.46) transparent}[type=checkbox]:disabled:not(:checked)+label:before{border:none;margin-left:2px;margin-top:2px;background-color:rgba(0,0,0,.46)}[type=checkbox]:disabled:indeterminate+label:before{border-right:2px solid rgba(0,0,0,.46);margin-left:0;margin-top:0;background-color:transparent}[type=checkbox][class*=filled-in]+label:after,[type=checkbox][class*=filled-in]+label:before{content:'';left:0;position:absolute;-webkit-transition:border .25s,background-color .25s,width .2s .1s,height .2s .1s,top .2s .1s,left .2s .1s;transition:border .25s,background-color .25s,width .2s .1s,height .2s .1s,top .2s .1s,left .2s .1s;z-index:1;border-style:solid;border-width:2px}[type=checkbox][class*=filled-in]+label:after{border-radius:2px;height:20px;width:20px}[type=checkbox][class*=filled-in]+label:before{-webkit-transform:rotateZ(37deg);-ms-transform:rotateZ(37deg);transform:rotateZ(37deg);-webkit-transform-origin:100% 100%;-ms-transform-origin:100% 100%;transform-origin:100% 100%}[type=checkbox][class*=filled-in]:not(:checked)+label:before{width:0;height:0;border-style:3px;border-color:transparent;left:6px;top:10px}[type=checkbox][class*=filled-in]:not(:checked)+label:after{background-color:transparent;border-color:#5a5a5a;top:0;z-index:0}[type=checkbox][class*=filled-in]:checked+label:before{top:0;left:1px;width:8px;height:13px;border-color:transparent #fff #fff transparent}[type=checkbox][class*=filled-in]:checked+label:after{border-color:#a6c;background-color:#a6c;z-index:0}[type=checkbox][class*=filled-in]:disabled:not(:checked)+label:before{background-color:transparent;border-color:#BDBDBD}[type=checkbox][class*=filled-in]:disabled:not(:checked)+label:after{border-color:transparent;background-color:#BDBDBD}[type=checkbox][class*=filled-in]:disabled:checked+label:before{background-color:transparent}[type=checkbox][class*=filled-in]:disabled:checked+label:after{background-color:#BDBDBD;border-color:#BDBDBD}[type=checkbox].filled-in-danger:checked+label:after{background-color:red;border-color:red}.select-wrapper .select-dropdown{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.clockpicker-plate,.picker,.switch,.switch *{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.select-label{position:absolute}.select-wrapper{position:relative}.select-wrapper input.select-dropdown{position:relative;cursor:pointer;background-color:transparent;border:none;border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:#bdbdbd;outline:0;height:3rem;line-height:3rem;width:100%;font-size:1rem;margin:0 0 15px;padding:0;display:block}.select-wrapper input.select-dropdown:disabled{color:rgba(0,0,0,.3);border-bottom-color:rgba(0,0,0,.3);cursor:default}.select-wrapper .search-wrap{padding:1rem 0;width:93%;display:block;margin:0 auto}.select-wrapper .search-wrap input{padding-bottom:.4rem}.select-wrapper span.caret{color:initial;position:absolute;right:0;top:16px;font-size:10px}.select-wrapper span.caret.disabled{color:rgba(0,0,0,.46)}.select-wrapper i,select:disabled{color:rgba(0,0,0,.3)}.select-wrapper+label{position:absolute;top:-14px;font-size:.8rem}.select-wrapper ul{list-style-type:none;padding-left:0}select{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;display:none!important}select.browser-default{display:block!important}.switch label .lever,.switch label .lever:after{display:inline-block;content:""}.select-dropdown ul{list-style-type:none;padding:0}.select-dropdown li img{height:30px;width:30px;margin:3px 12px;float:right}.select-dropdown li.disabled,.select-dropdown li.disabled>span,.select-dropdown li.optgroup{color:rgba(0,0,0,.3);background-color:transparent!important;cursor:context-menu}.select-dropdown li.optgroup{border-top:1px solid #eee}.select-dropdown li.optgroup.selected>span{color:rgba(0,0,0,.7)}.select-dropdown li.optgroup>span{color:rgba(0,0,0,.4)}.multiple-select-dropdown li [type=checkbox]+label{height:10px}.switch,.switch *{-khtml-user-select:none}.switch label{cursor:pointer}.switch label input[type=checkbox]{opacity:0;width:0;height:0}.switch label input[type=checkbox]:checked+.lever{background-color:#dccfe2}.switch label input[type=checkbox]:checked+.lever:after{background-color:#a6c;left:24px}.switch label input[type=checkbox]:checked:not(:disabled)~.lever:active:after{-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.4),0 0 0 15px rgba(170,102,204,.1);box-shadow:0 1px 3px 1px rgba(0,0,0,.4),0 0 0 15px rgba(170,102,204,.1)}.switch label input[type=checkbox]:not(:disabled)~.lever:active:after{-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.4),0 0 0 15px rgba(0,0,0,.08);box-shadow:0 1px 3px 1px rgba(0,0,0,.4),0 0 0 15px rgba(0,0,0,.08)}.switch label input[type=checkbox]:disabled+.lever{cursor:default}.switch label input[type=checkbox]:disabled+.lever:after,.switch label input[type=checkbox]:disabled:checked+.lever:after{background-color:#BDBDBD}.switch label .lever{position:relative;width:40px;height:15px;background-color:#818181;border-radius:15px;-webkit-transition:background .3s ease;transition:background .3s ease;margin:0 16px}.switch label .lever:after{position:absolute;width:21px;height:21px;background-color:#F1F1F1;border-radius:21px;-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.4);box-shadow:0 1px 3px 1px rgba(0,0,0,.4);left:-5px;top:-3px;-webkit-transition:left .3s ease,background .3s ease,box-shadow .1s ease;-webkit-transition:left .3s ease,background .3s ease,-webkit-box-shadow .1s ease;transition:left .3s ease,background .3s ease,-webkit-box-shadow .1s ease;transition:left .3s ease,background .3s ease,box-shadow .1s ease;transition:left .3s ease,background .3s ease,box-shadow .1s ease,-webkit-box-shadow .1s ease}.file-field{position:relative}.file-field .file-path-wrapper{overflow:hidden;padding-left:10px;height:2.5rem}.file-field input.file-path{width:100%;height:2.1rem}.file-field .btn{float:left}.file-field span{cursor:pointer}.file-field input[type=file]{position:absolute;top:0;right:0;left:0;bottom:0;width:100%;margin:0;padding:0;font-size:1px;cursor:pointer;opacity:0;filter:alpha(opacity=0)}.range-field,input[type=range]{position:relative}.btn-file{padding-top:1px}input[type=range]{cursor:pointer;background-color:transparent;outline:0;width:100%;margin:15px 0;padding:0;border:1px solid #fff}input[type=range]:focus{outline:0}input[type=range]+.thumb{position:absolute;border:none;height:0;width:0;border-radius:50%;background-color:#4285F4;top:10px;margin-left:-6px;-webkit-transform-origin:50% 50%;-ms-transform-origin:50% 50%;transform-origin:50% 50%;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}input[type=range]+.thumb .value{display:block;width:30px;color:#4285F4;font-size:0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}input[type=range]+.thumb.active{border-radius:50% 50% 50% 0}input[type=range]+.thumb.active .value{color:#fff;margin-left:-1px;margin-top:8px;font-size:10px}input[type=range]::-webkit-slider-runnable-track{height:3px;background:#c2c0c2;border:none}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;border:none;height:14px;width:14px;border-radius:50%;background-color:#4285F4;-webkit-transform-origin:50% 50%;transform-origin:50% 50%;margin:-5px 0 0;-webkit-transition:.3s;transition:.3s}input[type=range]:focus::-webkit-slider-runnable-track{background:#ccc}input[type=range]::-moz-range-track{height:3px;background:#ddd;border:none}input[type=range]::-moz-range-thumb{border:none;height:14px;width:14px;border-radius:50%;background:#4285F4;margin-top:-5px}input[type=range]:-moz-focusring{outline:#fff solid 1px;outline-offset:-1px}input[type=range]:focus::-moz-range-track{background:#ccc}input[type=range]::-ms-track{height:3px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input[type=range]::-ms-fill-lower{background:#777}input[type=range]::-ms-fill-upper{background:#ddd}input[type=range]::-ms-thumb{border:none;height:14px;width:14px;border-radius:50%;background:#4285F4}input[type=range]:focus::-ms-fill-lower{background:#888}input[type=range]:focus::-ms-fill-upper{background:#ccc}.input-group .input-group-addon{background-color:#e0e0e0}.input-group .input-group-addon [type=checkbox]+label{padding-left:18px;height:13px}.input-group .input-group-addon [type=radio]+label{padding-left:24px;height:13px}.input-group .input-group-addon:-moz-placeholder{padding-left:1rem}.input-group .input-group-addon::-ms-placeholder{padding-left:1rem}.input-group .input-group-addon::-webkit-input-placeholder{padding-left:1rem}.input-group .input-group-addon::-moz-placeholder{padding-left:1rem}.input-group .input-group-addon:-ms-input-placeholder{padding-left:1rem}.input-group .input-group-addon::placeholder{padding-left:1rem}.input-group span{z-index:10}.input-group .form-control{margin-top:3px;padding-top:14px;padding-bottom:7px;padding-left:1.2rem}.mdb-autocomplete{margin-bottom:1px}.side-nav .about p,.side-nav .search-form .form-control{margin-bottom:0}.mdb-autocomplete-clear{visibility:hidden;position:absolute;z-index:2;right:0;top:.85rem;background:0 0;border:none}.side-nav .collapsible a.active,.side-nav .collapsible a:hover,.side-nav .collapsible>li{border-radius:2px}.side-nav .about,.side-nav .social{border-bottom:1px solid rgba(153,153,153,.3)}.mdb-autocomplete-clear svg{fill:#a6a6a6}.mdb-autocomplete-wrap{position:absolute;left:0;right:0;background:#fff;box-shadow:0 2px 5px rgba(0,0,0,.25);z-index:100;max-height:210px;overflow-y:auto;padding-left:0;list-style-type:none}.mdb-autocomplete-wrap li{cursor:pointer;padding:12px 15px;font-size:.875rem}.mdb-autocomplete-wrap li:hover{background:#eee}.jarallax,.side-nav{background-size:cover;background-repeat:no-repeat;background-position:center}.jarallax{min-height:700px}.side-nav{position:fixed;width:240px;left:0;top:0;margin:0;height:100%;height:-webkit-calc(100%+ 60px);height:calc(100%+ 60px);height:-moz-calc(100%);color:#d8d8d8;background-color:#2c2f34;z-index:999;overflow:hidden;will-change:transform;backface-visibility:hidden;-webkit-transform:translateX(-105%);-ms-transform:translateX(-105%);transform:translateX(-105%);list-style-type:none;padding:0}.side-nav ul{list-style-type:none}.side-nav ul li{padding:0}.side-nav.right-aligned{right:0;left:auto;-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.side-nav .collapsible{margin:0;padding:0}.side-nav .collapsible li a:hover{background-color:rgba(0,0,0,.15)}.side-nav .collapsible>li a.collapsible-header.active,.side-nav .collapsible>li a.collapsible-header:hover{background-color:rgba(255,255,255,.15)}.side-nav .collapsible ul{padding:0;list-style-type:none}.side-nav .collapsible a{color:#fff;font-weight:300;font-size:.8rem}.side-nav .collapsible .fa{font-size:.8rem;margin-right:13px}.side-nav .collapsible-body a{padding-left:47px;height:36px;line-height:36px;background-color:rgba(0,0,0,.15)}.side-nav a{display:block;font-size:1rem;height:56px;line-height:56px;padding-left:20px}.side-nav .logo-wrapper{height:140px}.side-nav .logo-wrapper a{height:140px;width:240px;padding:0}.side-nav .logo-wrapper img{height:auto;padding:20% 50px}@media (max-height:992px){.side-nav .logo-wrapper,.side-nav .logo-wrapper a{height:80px}.side-nav .logo-wrapper img{padding:7% 50px}}.side-nav .about{padding:1rem}.side-nav .social{padding:0}.side-nav .social li{display:inline-block;padding:0;margin:0}.side-nav .social a{padding:0 .6rem;margin:0}.side-nav .social .fa{color:#dbe4e7}.side-nav .search-form{padding:0}.side-nav .search-form input[type=text]{font-weight:300;padding-left:30px}.side-nav .search-form input[type=text]:-moz-placeholder{color:#fff!important}.side-nav .search-form input[type=text]::-ms-placeholder{color:#fff!important}.side-nav .search-form input[type=text]::-webkit-input-placeholder{color:#fff!important}.side-nav .search-form input[type=text]::-moz-placeholder{color:#fff!important}.side-nav .search-form input[type=text]:-ms-input-placeholder{color:#fff!important}.side-nav .search-form input[type=text]::placeholder{color:#fff!important}.side-nav .sn-avatar-wrapper{padding-left:33%;padding-right:33%;padding-top:10%}.side-nav .sn-avatar-wrapper img{margin:0;padding:0;max-width:90px;border-radius:5rem}@media only screen and (max-height:992px){.side-nav .sn-avatar-wrapper{padding-left:40%;padding-right:40%;padding-top:3%}.side-nav .sn-avatar-wrapper img{max-width:50px}}.side-nav .sn-ad-avatar-wrapper{height:auto;margin-bottom:0}.side-nav .sn-ad-avatar-wrapper img{max-width:60px;padding:20px 10px;float:left}.side-nav .sn-ad-avatar-wrapper p{font-size:15px;padding-top:20px;padding-bottom:20px;margin:0}.side-nav .user-box{padding:20px 10px 0}.side-nav .user-box img{margin:0 auto 10px;max-width:80px}.side-nav .fa-angle-down.rotate-icon{position:absolute;right:0;margin-right:20px}.side-nav .sidenav-bg{top:0;bottom:0;left:0;right:0;width:240px;z-index:-1;background-attachment:fixed}.side-nav .sidenav-bg:after{width:100%;display:block;content:"";position:absolute;height:100%;top:0;left:0;bottom:0;z-index:-1;margin-bottom:-99999px;padding-bottom:99999px}.side-nav.fixed{left:0;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0);position:fixed}.side-nav.fixed.right-aligned{right:0;left:auto}@media only screen and (max-width:1440px){.side-nav.fixed{-webkit-transform:translateX(-105%);-ms-transform:translateX(-105%);transform:translateX(-105%)}.side-nav.fixed.right-aligned{-webkit-transform:translateX(105%);-ms-transform:translateX(105%);transform:translateX(105%)}}.side-nav.side-nav-light{background-color:#e5e5e5}.side-nav.side-nav-light a{color:#555;font-weight:400}.side-nav.side-nav-light .social .fa{color:#555}.side-nav.side-nav-light .search-form input[type=text]{border-bottom-color:rgba(153,153,153,.3);color:#555!important}.side-nav.side-nav-light .search-form input[type=text]:-moz-placeholder{color:#555!important}.side-nav.side-nav-light .search-form input[type=text]::-ms-placeholder{color:#555!important}.side-nav.side-nav-light .search-form input[type=text]::-webkit-input-placeholder{color:#555!important}.side-nav.side-nav-light .search-form input[type=text]::-moz-placeholder{color:#555!important}.side-nav.side-nav-light .search-form input[type=text]:-ms-input-placeholder{color:#555!important}.side-nav.side-nav-light .search-form input[type=text]::placeholder{color:#555!important}.side-nav.side-nav-light .collapsible-body a{background-color:rgba(0,0,0,.1)}.side-nav.side-nav-light .collapsible li .collapsible-header:hover{background-color:rgba(0,0,0,.05)}.side-nav.side-nav-light .collapsible li .collapsible-header.active{color:#4285F4;background-color:transparent}.drag-target{height:100%;width:10px;position:fixed;top:0;z-index:998}#sidenav-overlay{position:fixed;top:0;left:0;right:0;height:120vh;background-color:rgba(0,0,0,.5);z-index:997;will-change:opacity}.side-nav .double-navbar .bc-min{padding:5px 10px}.no-padding .fa,.rating{padding:0}.side-nav .double-navbar .bc-min .button-collapse{padding-left:0}.rating{list-style-type:none}.rating li{display:inline-block}.product-panel .modal-dialog,.ql-modal .modal-dialog{max-width:none;width:auto;margin:2rem}.product-panel .price .badge,.ql-modal .price .badge{background-color:rgba(244,67,54,.7);font-size:1.4rem;display:inline-block;margin-left:1rem}.product-panel .price p,.ql-modal .price p{display:inline-block;font-size:1.3rem}.product-panel .price p .price-before,.ql-modal .price p .price-before{color:#000;text-decoration:line-through;margin-left:.5rem}.product-panel .price p .price-after,.ql-modal .price p .price-after{font-size:1.7rem;color:green}.product-panel .media img,.ql-modal .media img{max-width:60px}@media (max-width:1200px){.ql-modal{padding-left:0}.ql-modal .modal-dialog{margin:0}}.wishlist{background-color:#ff3547}.collection-card .stripe{position:absolute;bottom:3rem;width:100%;text-align:center;padding:1.2rem}.collection-card .stripe.dark{background-color:rgba(0,0,0,.7)}.collection-card .stripe.dark a p{color:#eee}.collection-card .stripe.light{background-color:rgba(255,255,255,.7)}.collection-card .stripe.light a p{color:#424242}.collection-card .stripe a p{padding:0;margin:0;letter-spacing:4px;font-size:1rem}.cart-modal .table .total{text-transform:uppercase;font-weight:600}.cart-modal .table .fa-remove{color:#4285F4}.carousel-multi-item{margin-bottom:100px}@media (min-width:768px){.carousel-multi-item .col-md-4{float:left;width:33.333333%;max-width:100%}}.carousel-multi-item .carousel-item-next,.carousel-multi-item .carousel-item-prev,.carousel-multi-item .carousel-item.active{display:block}.carousel-multi-item .carousel-indicators li{height:20px;max-width:20px;background-color:#4285F4;margin-bottom:-60px}.carousel-multi-item .carousel-indicators .active{height:25px;max-width:25px;background-color:#4285F4;border-radius:50%}.carousel-multi-item .controls-top{margin-bottom:30px}.carousel-multi-item .controls-top .btn-floating{background:#4285F4}.carousel-multi-item .carousel-indicators{margin-bottom:-2em}.carousel-multi-item .card{margin:1px}.carousel-multi-item .card-cascade.narrower{margin-top:20px;margin-bottom:5px}@media only screen and (max-width:992px){.carousel-multi-item .carousel-indicators li{margin-bottom:-30px}}.carousel-thumbnails{margin-bottom:80px}.carousel-thumbnails .carousel-indicators{margin-bottom:-75px;position:absolute}.carousel-thumbnails .carousel-indicators li{height:auto;max-width:100px;width:100px;border:none}.carousel-thumbnails .carousel-indicators .active{height:auto;width:auto;opacity:.5}.carousel-thumbnails .carousel-indicators img{max-width:100px;height:50px;overflow:hidden;display:block}@media only screen and (max-width:600px){.carousel-thumbnails{margin-bottom:60px}.carousel-thumbnails .carousel-indicators{margin-bottom:-60px}.carousel-thumbnails .carousel-indicators img{max-width:50px;height:25px}}.stepper li a{padding:24px;font-size:14px}.stepper li a .circle{display:inline-block;color:#fff;border-radius:50%;background:rgba(0,0,0,.38);width:24px;height:24px;line-height:24px;margin-right:8px}.stepper li a .label{display:inline-block;color:rgba(0,0,0,.38)}.stepper li.active a .label,.stepper li.completed a .label{font-weight:600;color:rgba(0,0,0,.87)}.stepper-horizontal{position:relative;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.stepper-horizontal li{-webkit-transition:.5s;transition:.5s;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.stepper-vertical,.stepper-vertical li{position:relative}.stepper-horizontal li a .label{margin-top:10px}.stepper-horizontal li:not(:first-child):before,.stepper-horizontal li:not(:last-child):after{content:'';position:relative;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;margin:8px 0 0;height:1px;background-color:rgba(0,0,0,.1)}.error404,.stepper-vertical{-webkit-flex-direction:column}.stepper-horizontal li:hover{background:#ddd}.stepper-vertical{display:flex;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.stepper-vertical li{display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.stepper-vertical li a{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;position:relative}.stepper-vertical li a .circle{-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}.stepper-vertical li a .label{-webkit-flex-flow:column nowrap;-ms-flex-flow:column nowrap;flex-flow:column nowrap;-webkit-box-ordinal-group:3;-webkit-order:2;-ms-flex-order:2;order:2}.stepper-vertical li.completed a .label{font-weight:500}.stepper-vertical li .step-content{display:block;margin-top:0;margin-left:50px;padding:15px}.stepper-vertical li .step-content p{font-size:.875rem}.stepper-vertical li:not(:last-child):after{content:" ";position:absolute;width:1px;height:-webkit-calc(100% - 40px);height:calc(100% - 40px);left:35px;top:55px;background-color:rgba(0,0,0,.1)}.author-box{padding:3rem}@media (max-width:601px){.author-box{text-align:center}.author-box img{margin-bottom:2rem;display:inline}}.author-box strong{font-weight:600}.comments-list,.reply-form{margin-bottom:3rem}.comments-list ul,.reply-form ul{list-style-type:none}.comments-list img,.reply-form img{max-width:100px;border-radius:50%}.comments-list .row,.reply-form .row{margin-bottom:2rem}.comments-list .user-name,.reply-form .user-name{color:#000}.comments-list .comment-date,.reply-form .comment-date{color:#666}.comments-list .comment-text,.reply-form .comment-text{color:#9e9e9e}@media (max-width:601px){.comments-list,.reply-form{text-align:center}.comments-list img,.reply-form img{display:inline;margin-bottom:1rem}.comments-list .md-form,.reply-form .md-form{text-align:left}}.comments-list .text-center,.reply-form .text-center{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.section-blog-fw h2{margin-bottom:1rem}.personal-sm{margin-bottom:10px}.personal-sm a{padding:5px}.personal-sm a:first-of-type{padding-left:0}.personal-sm a .fa{-webkit-transition-duration:.2s;transition-duration:.2s}.personal-sm a:hover .fa{-webkit-transform:scale(1.2);-ms-transform:scale(1.2);transform:scale(1.2)}.toast-title{font-weight:700}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a:hover{color:#ccc;text-decoration:none}.white-skin .navbar .navbar-nav .nav-item a,.white-skin .navbar.double-nav a,.white-skin .side-nav .social a .fa{color:#424242}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:progid: DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}.toast-top-center,.toast-top-full-width{top:0;right:0;width:100%}.clockpicker-display .clockpicker-display-column,.picker__date-display .clockpicker-display .clockpicker-display-column{float:left}.toast-close-button:focus,.toast-close-button:hover{text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:progid: DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-bottom-center,.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999}#toast-container *{-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;background-position:15px center;background-repeat:no-repeat;opacity:.95;-ms-filter:progid: DXImageTransform.Microsoft.Alpha(Opacity=95);filter:alpha(opacity=95)}#toast-container>:hover{-webkit-transition:.45s;transition:.45s;-webkit-box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 8px 17px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);opacity:1;-ms-filter:progid: DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin:auto}.toast{background-color:#030303}.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:progid: DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}}.collapsible .active .rotate-icon{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg);-webkit-transition:all 150ms ease-in 0s;transition:all 150ms ease-in 0s}.min-chart{position:relative;display:inline-block;width:110px;height:110px;margin-top:50px;margin-bottom:50px;text-align:center}.min-chart canvas{position:absolute;top:0;left:0}.min-chart .percent{display:inline-block;line-height:110px;z-index:2}.min-chart .percent:after{content:'%';margin-left:.1em;font-size:.8em}.progress{box-shadow:none;position:relative;display:block;width:100%;height:4px;overflow:hidden;margin-bottom:1rem;background-color:#eee}.progress .progress-bar{-webkit-box-shadow:none;box-shadow:none;height:4px;border-radius:0;background-color:#0d47a1}.progress .progress-bar-animated{-webkit-transition:width 2s ease-in-out;transition:width 2s ease-in-out}.progress .indeterminate{background-color:#90caf9}.progress .indeterminate:after,.progress .indeterminate:before{content:'';position:absolute;background-color:inherit;left:0;will-change:left,right;top:0;bottom:0}.progress .indeterminate:before{-webkit-animation:indeterminate 2.1s cubic-bezier(.65,.815,.735,.395) infinite;animation:indeterminate 2.1s cubic-bezier(.65,.815,.735,.395) infinite}.progress .indeterminate:after{-webkit-animation:indeterminate-short 2.1s cubic-bezier(.165,.84,.44,1) infinite;animation:indeterminate-short 2.1s cubic-bezier(.165,.84,.44,1) infinite;-webkit-animation-delay:1.15s;animation-delay:1.15s}@-webkit-keyframes indeterminate{0%{left:-35%;right:100%}100%,60%{left:100%;right:-90%}}@keyframes indeterminate{0%{left:-35%;right:100%}100%,60%{left:100%;right:-90%}}@-webkit-keyframes indeterminate-short{0%{left:-200%;right:100%}100%,60%{left:107%;right:-8%}}@keyframes indeterminate-short{0%{left:-200%;right:100%}100%,60%{left:107%;right:-8%}}.preloader-wrapper{display:inline-block;position:relative;width:48px;height:48px}.preloader-wrapper.small{width:36px;height:36px}.preloader-wrapper.big{width:64px;height:64px}.preloader-wrapper.active{-webkit-animation:container-rotate 1568ms linear infinite;animation:container-rotate 1568ms linear infinite}.preloader-wrapper.crazy{-webkit-animation-duration:333ms;animation-duration:333ms}.preloader-wrapper .spinner-layer{position:absolute;width:100%;height:100%;opacity:0}.preloader-wrapper .spinner-layer .gap-patch{position:absolute;top:0;left:45%;width:10%;height:100%;overflow:hidden;border-color:inherit}.preloader-wrapper .spinner-layer .gap-patch .circle{width:1000%;left:-450%}.preloader-wrapper .spinner-layer .circle-clipper{display:inline-block;position:relative;width:50%;height:100%;overflow:hidden;border-color:inherit}.preloader-wrapper .spinner-layer .circle-clipper .circle{width:200%;height:100%;border-width:3px;border-style:solid;border-color:inherit;border-bottom-color:transparent!important;border-radius:50%;-webkit-animation:none;animation:none;position:absolute;top:0;right:0;bottom:0}.preloader-wrapper .spinner-layer .circle-clipper.left .circle{left:0;border-right-color:transparent!important;-webkit-transform:rotate(129deg);-ms-transform:rotate(129deg);transform:rotate(129deg)}.preloader-wrapper .spinner-layer .circle-clipper.right .circle{left:-100%;border-left-color:transparent!important;-webkit-transform:rotate(-129deg);-ms-transform:rotate(-129deg);transform:rotate(-129deg)}.preloader-wrapper .spinner-blue,.preloader-wrapper .spinner-blue-only{border-color:#4285f4}.preloader-wrapper .spinner-red,.preloader-wrapper .spinner-red-only{border-color:#db4437}.preloader-wrapper .spinner-yellow,.preloader-wrapper .spinner-yellow-only{border-color:#f4b400}.preloader-wrapper .spinner-green,.preloader-wrapper .spinner-green-only{border-color:#0f9d58}@-webkit-keyframes container-rotate{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes container-rotate{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.active .spinner-layer.spinner-blue{-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both,blue-fade-in-out 5332ms cubic-bezier(.4,0,.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both,blue-fade-in-out 5332ms cubic-bezier(.4,0,.2,1) infinite both}.active .spinner-layer.spinner-red{-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both,red-fade-in-out 5332ms cubic-bezier(.4,0,.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both,red-fade-in-out 5332ms cubic-bezier(.4,0,.2,1) infinite both}.active .spinner-layer.spinner-yellow{-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both,yellow-fade-in-out 5332ms cubic-bezier(.4,0,.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both,yellow-fade-in-out 5332ms cubic-bezier(.4,0,.2,1) infinite both}.active .spinner-layer.spinner-green{-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both,green-fade-in-out 5332ms cubic-bezier(.4,0,.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both,green-fade-in-out 5332ms cubic-bezier(.4,0,.2,1) infinite both}.active .spinner-layer.spinner-blue-only,.active .spinner-layer.spinner-green-only,.active .spinner-layer.spinner-primary-color-only,.active .spinner-layer.spinner-red-only,.active .spinner-layer.spinner-yellow-only{opacity:1;-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(.4,0,.2,1) infinite both}.active .circle-clipper.left .circle{-webkit-animation:left-spin 1333ms cubic-bezier(.4,0,.2,1) infinite both;animation:left-spin 1333ms cubic-bezier(.4,0,.2,1) infinite both}.active .circle-clipper.right .circle{-webkit-animation:right-spin 1333ms cubic-bezier(.4,0,.2,1) infinite both;animation:right-spin 1333ms cubic-bezier(.4,0,.2,1) infinite both}@-webkit-keyframes fill-unfill-rotate{12.5%{-webkit-transform:rotate(135deg);transform:rotate(135deg)}25%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}37.5%{-webkit-transform:rotate(405deg);transform:rotate(405deg)}50%{-webkit-transform:rotate(540deg);transform:rotate(540deg)}62.5%{-webkit-transform:rotate(675deg);transform:rotate(675deg)}75%{-webkit-transform:rotate(810deg);transform:rotate(810deg)}87.5%{-webkit-transform:rotate(945deg);transform:rotate(945deg)}to{-webkit-transform:rotate(1080deg);transform:rotate(1080deg)}}@keyframes fill-unfill-rotate{12.5%{-webkit-transform:rotate(135deg);transform:rotate(135deg)}25%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}37.5%{-webkit-transform:rotate(405deg);transform:rotate(405deg)}50%{-webkit-transform:rotate(540deg);transform:rotate(540deg)}62.5%{-webkit-transform:rotate(675deg);transform:rotate(675deg)}75%{-webkit-transform:rotate(810deg);transform:rotate(810deg)}87.5%{-webkit-transform:rotate(945deg);transform:rotate(945deg)}to{-webkit-transform:rotate(1080deg);transform:rotate(1080deg)}}@-webkit-keyframes blue-fade-in-out{100%,25%,90%,from{opacity:1}26%,89%{opacity:0}}@keyframes blue-fade-in-out{100%,25%,90%,from{opacity:1}26%,89%{opacity:0}}@-webkit-keyframes red-fade-in-out{15%,51%,from{opacity:0}25%,50%{opacity:1}}@keyframes red-fade-in-out{15%,51%,from{opacity:0}25%,50%{opacity:1}}@-webkit-keyframes yellow-fade-in-out{40%,76%,from{opacity:0}50%,75%{opacity:1}}@keyframes yellow-fade-in-out{40%,76%,from{opacity:0}50%,75%{opacity:1}}@-webkit-keyframes green-fade-in-out{100%,65%,from{opacity:0}75%,90%{opacity:1}}@keyframes green-fade-in-out{100%,65%,from{opacity:0}75%,90%{opacity:1}}@-webkit-keyframes left-spin{from,to{-webkit-transform:rotate(130deg);transform:rotate(130deg)}50%{-webkit-transform:rotate(-5deg);transform:rotate(-5deg)}}@keyframes left-spin{from,to{-webkit-transform:rotate(130deg);transform:rotate(130deg)}50%{-webkit-transform:rotate(-5deg);transform:rotate(-5deg)}}@-webkit-keyframes right-spin{from,to{-webkit-transform:rotate(-130deg);transform:rotate(-130deg)}50%{-webkit-transform:rotate(5deg);transform:rotate(5deg)}}@keyframes right-spin{from,to{-webkit-transform:rotate(-130deg);transform:rotate(-130deg)}50%{-webkit-transform:rotate(5deg);transform:rotate(5deg)}}#spinnerContainer.cooldown{-webkit-animation:container-rotate 1568ms linear infinite,fade-out .4s cubic-bezier(.4,0,.2,1);animation:container-rotate 1568ms linear infinite,fade-out .4s cubic-bezier(.4,0,.2,1)}@-webkit-keyframes fade-out{from{opacity:1}to{opacity:0}}@keyframes fade-out{from{opacity:1}to{opacity:0}}#mdb-preloader{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#000;z-index:9998;height:100%;width:100%}.ps{-ms-touch-action:auto;touch-action:auto;overflow:hidden!important}.ps.ps--active-x>.ps__scrollbar-x-rail,.ps.ps--active-y>.ps__scrollbar-y-rail{display:block;background-color:transparent}.ps.ps--active-y>.ps__scrollbar-y-rail{top:0!important}.ps.ps--in-scrolling.ps--x>.ps__scrollbar-x-rail{background-color:#eee;opacity:.9}.ps.ps--in-scrolling.ps--x>.ps__scrollbar-x-rail>.ps__scrollbar-x{background-color:#999;height:11px}.ps>.ps__scrollbar-x-rail{display:none;position:absolute;opacity:0;-webkit-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear;bottom:0;height:15px}.ps>.ps__scrollbar-x-rail>.ps__scrollbar-x{position:absolute;background-color:#aaa;border-radius:6px;-webkit-transition:background-color .2s linear,height .2s linear,width .2s ease-in-out,border-radius .2s ease-in-out;transition:background-color .2s linear,height .2s linear,width .2s ease-in-out,border-radius .2s ease-in-out;bottom:2px;height:6px}.ps>.ps__scrollbar-x-rail:hover>.ps__scrollbar-x,.ps>.ps__scrollbar-x-rail>.ps__scrollbar-x-rail:active>.ps__scrollbar-x{height:11px}.ps.ps--in-scrolling.ps--y>.ps__scrollbar-y-rail{background-color:#eee;opacity:.9}.ps.ps--in-scrolling.ps--y>.ps__scrollbar-y-rail>.ps__scrollbar-y{background-color:#999;width:11px}.ps>.ps__scrollbar-y-rail{display:none;position:absolute;opacity:0;-webkit-transition:background-color .2s linear,opacity .2s linear;transition:background-color .2s linear,opacity .2s linear;right:0;width:15px;z-index:999}.ps>.ps__scrollbar-y-rail>.ps__scrollbar-y{position:absolute;background-color:#aaa;border-radius:6px;-webkit-transition:background-color .2s linear,height .2s linear,width .2s ease-in-out,border-radius .2s ease-in-out;transition:background-color .2s linear,height .2s linear,width .2s ease-in-out,border-radius .2s ease-in-out;right:2px;width:6px}.ps>.ps__scrollbar-y-rail:hover>.ps__scrollbar-y,.ps>.ps__scrollbar-y-rail>.ps__scrollbar-y-rail:active>.ps__scrollbar-y{width:11px}.ps:hover.ps--in-scrolling.ps--x>.ps__scrollbar-x-rail{background-color:#eee;opacity:.9}.ps:hover.ps--in-scrolling.ps--x>.ps__scrollbar-x-rail>.ps__scrollbar-x{background-color:#999;height:11px}.ps:hover.ps--in-scrolling.ps--y>.ps__scrollbar-y-rail{background-color:#eee;opacity:.9}.ps:hover.ps--in-scrolling.ps--y>.ps__scrollbar-y-rail>.ps__scrollbar-y{background-color:#999;width:11px}.ps:hover>.ps__scrollbar-x-rail,.ps:hover>.ps__scrollbar-y-rail{opacity:.6}.ps:hover>.ps__scrollbar-x-rail:hover{background-color:#eee;opacity:.9}.ps:hover>.ps__scrollbar-x-rail:hover>.ps__scrollbar-x{background-color:#999}.ps:hover>.ps__scrollbar-y-rail:hover{background-color:#eee;opacity:.9}.ps:hover>.ps__scrollbar-y-rail:hover>.ps__scrollbar-y{background-color:#999}.sn-bg-1{background-image:url(https://mdbootstrap.com/img/Photos/Others/sidenav1.jpg)}.sn-bg-2{background-image:url(https://mdbootstrap.com/img/Photos/Others/sidenav2.jpg)}.sn-bg-3{background-image:url(https://mdbootstrap.com/img/Photos/Others/sidenav3.jpg)}.sn-bg-4{background-image:url(https://mdbootstrap.com/img/Photos/Others/sidenav4.jpg)}.white-skin .gradient{background:#ababab;background:-webkit-linear-gradient(315deg,#ababab 0,#fff 100%);background:linear-gradient(135deg,#ababab 0,#fff 100%)}.stepper li.active a .white-skin .circle,.stepper li.completed a .white-skin .circle,.white-skin .primary-color,.white-skin .stepper li.active a .circle,.white-skin .stepper li.completed a .circle{background-color:#4285F4!important}.white-skin .navbar{background-color:#fff;color:#424242}.white-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.white-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.white-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#2a75f3}.white-skin .page-footer{background-color:#6f7178}.white-skin .side-nav{background-color:#F9F9F9}.white-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.white-skin .side-nav .sn-avatar-wrapper img{border:3px solid #0d5bdd}.white-skin .side-nav .social a:hover .fa{color:#4285F4!important;-webkit-transition:all .3s linear;transition:all .3s linear}.white-skin .side-nav .search-form input[type=text]{color:#424242!important;border-bottom:1px solid rgba(153,153,153,.3)}.white-skin .side-nav .search-form input[type=text]:-moz-placeholder{color:rgba(66,66,66,.5)!important}.white-skin .side-nav .search-form input[type=text]::-ms-placeholder{color:rgba(66,66,66,.5)!important}.white-skin .side-nav .search-form input[type=text]::-webkit-input-placeholder{color:rgba(66,66,66,.5)!important}.white-skin .side-nav .search-form input[type=text]::-moz-placeholder{color:rgba(66,66,66,.5)!important}.white-skin .side-nav .search-form input[type=text]:-ms-input-placeholder{color:rgba(66,66,66,.5)!important}.white-skin .side-nav .search-form input[type=text]::placeholder{color:rgba(66,66,66,.5)!important}.white-skin .side-nav .collapsible li{background-color:transparent}.white-skin .side-nav .collapsible li a{font-weight:400}.white-skin .side-nav .collapsible li .collapsible-header{color:#424242;-webkit-transition:all .3s linear;transition:all .3s linear}.white-skin .side-nav .collapsible li .collapsible-header.active{color:#4285F4;background-color:transparent}.white-skin .side-nav .collapsible a:hover,.white-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(0,0,0,.05)}.white-skin .side-nav .collapsible li .collapsible-body a{color:#424242}.white-skin .side-nav .collapsible li .collapsible-body a:hover{color:#4285F4}.white-skin .side-nav .collapsible a{color:#424242;-webkit-transition:all .3s linear;transition:all .3s linear}.white-skin .side-nav .fa{color:#424242}.white-skin .dropdown-content li:not(.disabled) span,.white-skin .md-form .prefix.active,.white-skin input[type=email]:focus:not([readonly])+label,.white-skin input[type=password]:focus:not([readonly])+label,.white-skin input[type=text]:focus:not([readonly])+label,.white-skin textarea.md-textarea:focus:not([readonly])+label{color:#4285F4}.white-skin .side-nav .sidenav-bg.mask-strong:after,.white-skin .side-nav .sidenav-bg:after{background:rgba(255,255,255,.8)}.white-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(255,255,255,.65)}.white-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(255,255,255,.5)}.white-skin .btn-primary{background-color:#4285F4}.white-skin .btn-primary:hover{background-color:#5a95f5!important}.white-skin .btn-primary.active,.white-skin .btn-primary:active,.white-skin .btn-primary:focus{background-color:#0d5bdd!important}.white-skin .btn-primary.dropdown-toggle{background-color:#4285F4!important}.white-skin .btn-primary.dropdown-toggle:focus,.white-skin .btn-primary.dropdown-toggle:hover{background-color:#5a95f5!important}.white-skin .btn-secondary{background-color:#fc685f}.white-skin .btn-secondary:hover{background-color:#fc8078!important}.white-skin .btn-secondary.active,.white-skin .btn-secondary:active,.white-skin .btn-secondary:focus{background-color:#fb2114!important}.white-skin .btn-secondary.dropdown-toggle{background-color:#fc685f!important}.white-skin .btn-secondary.dropdown-toggle:focus,.white-skin .btn-secondary.dropdown-toggle:hover{background-color:#fc8078!important}.white-skin .btn-default{background-color:#454545}.white-skin .btn-default:hover{background-color:#525252!important}.white-skin .btn-default.active,.white-skin .btn-default:active,.white-skin .btn-default:focus{background-color:#1f1f1f!important}.white-skin .btn-default.dropdown-toggle{background-color:#454545!important}.white-skin .btn-default.dropdown-toggle:focus,.white-skin .btn-default.dropdown-toggle:hover{background-color:#525252!important}.white-skin .card .btn-action{background:#454545}.white-skin .card .btn-action:focus,.white-skin .card .btn-action:hover{background-color:#525252!important}.white-skin .card .btn-action.active{background-color:#121212!important}.white-skin input[type=email]:focus:not([readonly]),.white-skin input[type=password]:focus:not([readonly]),.white-skin input[type=text]:focus:not([readonly]),.white-skin textarea.md-textarea:focus:not([readonly]){border-color:#4285F4;-webkit-box-shadow:0 1px 0 0 #4285F4;box-shadow:0 1px 0 0 #4285F4}.white-skin input[type=checkbox]:checked+label:before{border-right:2px solid #4285F4;border-bottom:2px solid #4285F4}.white-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.white-skin input[type=checkbox].filled-in:checked+label:after{background-color:#4285F4;border-color:#4285F4}.white-skin .top-nav-collapse{background-color:#fff}.white-skin .carousel-multi-item .carousel-indicators li,.white-skin .carousel-multi-item .carousel-indicators li.active,.white-skin .carousel-multi-item .controls-top>a{background-color:#4285F4}.white-skin .card-header,.white-skin .form-header{background-color:#4c8bf5}.white-skin .spinner-primary-color,.white-skin .spinner-primary-color-only{border-color:#4285F4}.white-skin .pagination-primary-color .page-item.active .page-link,.white-skin .pagination-primary-color .page-item.active .page-link:focus,.white-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#4285F4;border-color:#4285F4}.white-skin .pagination-primary-color .page-link{color:#4285F4}.black-skin .gradient{background:#000;background:-webkit-linear-gradient(315deg,#000 0,#616161 100%);background:linear-gradient(135deg,#000 0,#616161 100%)}.black-skin .primary-color,.black-skin .stepper li.active a .circle,.black-skin .stepper li.completed a .circle,.stepper li.active a .black-skin .circle,.stepper li.completed a .black-skin .circle{background-color:#2AD1A3!important}.black-skin .navbar{background-color:#222;color:#fff}.black-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.black-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.black-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#26bc92}.black-skin .page-footer,.black-skin .side-nav{background-color:#222}.black-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.black-skin .side-nav .sn-avatar-wrapper img{border:3px solid #1d9171}.black-skin .side-nav .social a:hover .fa{color:#2AD1A3!important;-webkit-transition:all .3s linear;transition:all .3s linear}.black-skin .side-nav .collapsible li{background-color:transparent}.black-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.black-skin .side-nav .collapsible li .collapsible-header.active,.black-skin .side-nav .collapsible li .collapsible-header:hover{background-color:#2AD1A3}.black-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.black-skin .side-nav .collapsible li .collapsible-body a:hover{color:#2AD1A3}.black-skin .side-nav .fa{color:#fff}.black-skin .dropdown-content li:not(.disabled) span,.black-skin .md-form .prefix.active,.black-skin input[type=email]:focus:not([readonly])+label,.black-skin input[type=password]:focus:not([readonly])+label,.black-skin input[type=text]:focus:not([readonly])+label,.black-skin textarea.md-textarea:focus:not([readonly])+label{color:#2AD1A3}.black-skin .side-nav .sidenav-bg.mask-strong:after,.black-skin .side-nav .sidenav-bg:after{background:rgba(0,0,0,.8)}.black-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(0,0,0,.65)}.black-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(0,0,0,.5)}.black-skin .btn-primary{background-color:#2AD1A3}.black-skin .btn-primary:hover{background-color:#3dd8ad!important}.black-skin .btn-primary.active,.black-skin .btn-primary:active,.black-skin .btn-primary:focus{background-color:#1d9171!important}.black-skin .btn-primary.dropdown-toggle{background-color:#2AD1A3!important}.black-skin .btn-primary.dropdown-toggle:focus,.black-skin .btn-primary.dropdown-toggle:hover{background-color:#3dd8ad!important}.black-skin .btn-secondary{background-color:#0f478a}.black-skin .btn-secondary:hover{background-color:#1253a1!important}.black-skin .btn-secondary.active,.black-skin .btn-secondary:active,.black-skin .btn-secondary:focus{background-color:#082445!important}.black-skin .btn-secondary.dropdown-toggle{background-color:#0f478a!important}.black-skin .btn-secondary.dropdown-toggle:focus,.black-skin .btn-secondary.dropdown-toggle:hover{background-color:#1253a1!important}.black-skin .btn-default{background-color:#222}.black-skin .btn-default:hover{background-color:#2f2f2f!important}.black-skin .btn-default.active,.black-skin .btn-default:active,.black-skin .btn-default:focus{background-color:#000!important}.black-skin .btn-default.dropdown-toggle{background-color:#222!important}.black-skin .btn-default.dropdown-toggle:focus,.black-skin .btn-default.dropdown-toggle:hover{background-color:#2f2f2f!important}.black-skin .card .btn-action{background:#222}.black-skin .card .btn-action:focus,.black-skin .card .btn-action:hover{background-color:#2f2f2f!important}.black-skin .card .btn-action.active{background-color:#000!important}.black-skin input[type=email]:focus:not([readonly]),.black-skin input[type=password]:focus:not([readonly]),.black-skin input[type=text]:focus:not([readonly]),.black-skin textarea.md-textarea:focus:not([readonly]){border-color:#2AD1A3;-webkit-box-shadow:0 1px 0 0 #2AD1A3;box-shadow:0 1px 0 0 #2AD1A3}.black-skin input[type=checkbox]:checked+label:before{border-right:2px solid #2AD1A3;border-bottom:2px solid #2AD1A3}.black-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.black-skin input[type=checkbox].filled-in:checked+label:after{background-color:#2AD1A3;border-color:#2AD1A3}.black-skin .top-nav-collapse{background-color:#222}.black-skin .carousel-multi-item .carousel-indicators li,.black-skin .carousel-multi-item .carousel-indicators li.active,.black-skin .carousel-multi-item .controls-top>a{background-color:#2AD1A3}.black-skin .card-header,.black-skin .form-header{background-color:#30d5a8}.black-skin .spinner-primary-color,.black-skin .spinner-primary-color-only{border-color:#2AD1A3}.black-skin .pagination-primary-color .page-item.active .page-link,.black-skin .pagination-primary-color .page-item.active .page-link:focus,.black-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#2AD1A3;border-color:#2AD1A3}.black-skin .pagination-primary-color .page-link{color:#2AD1A3}.cyan-skin .gradient{background:#114861;background:-webkit-linear-gradient(315deg,#114861 0,#45b0c0 100%);background:linear-gradient(135deg,#114861 0,#45b0c0 100%)}.cyan-skin .primary-color,.cyan-skin .stepper li.active a .circle,.cyan-skin .stepper li.completed a .circle,.stepper li.active a .cyan-skin .circle,.stepper li.completed a .cyan-skin .circle{background-color:#4fada7!important}.cyan-skin .navbar{background-color:#114861;color:#fff}.cyan-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.cyan-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.cyan-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#eea82f}.cyan-skin .page-footer{background-color:#114861}.cyan-skin .side-nav{background-color:#24879d}.cyan-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.cyan-skin .side-nav .sn-avatar-wrapper img{border:3px solid #d99012}.cyan-skin .side-nav .social a:hover .fa{color:#f0b247!important;-webkit-transition:all .3s linear;transition:all .3s linear}.cyan-skin .side-nav .collapsible li{background-color:transparent}.cyan-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.cyan-skin .side-nav .collapsible li .collapsible-header.active,.cyan-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(29,65,82,.8)}.cyan-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.cyan-skin .side-nav .collapsible li .collapsible-body a:hover{color:#ffa742}.cyan-skin .side-nav .fa{color:#fff}.cyan-skin .dropdown-content li:not(.disabled) span,.cyan-skin .md-form .prefix.active,.cyan-skin input[type=email]:focus:not([readonly])+label,.cyan-skin input[type=password]:focus:not([readonly])+label,.cyan-skin input[type=text]:focus:not([readonly])+label,.cyan-skin textarea.md-textarea:focus:not([readonly])+label{color:#f0b247}.cyan-skin .side-nav .sidenav-bg.mask-strong:after,.cyan-skin .side-nav .sidenav-bg:after{background:rgba(21,78,96,.8)}.cyan-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(21,78,96,.65)}.cyan-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(21,78,96,.5)}.cyan-skin .btn-primary{background-color:#ffa742}.cyan-skin .btn-primary:hover{background-color:#ffb35c!important}.cyan-skin .btn-primary.active,.cyan-skin .btn-primary:active,.cyan-skin .btn-primary:focus{background-color:#f58300!important}.cyan-skin .btn-primary.dropdown-toggle{background-color:#ffa742!important}.cyan-skin .btn-primary.dropdown-toggle:focus,.cyan-skin .btn-primary.dropdown-toggle:hover{background-color:#ffb35c!important}.cyan-skin .btn-secondary{background-color:#45b0c0}.cyan-skin .btn-secondary:hover{background-color:#58b8c6!important}.cyan-skin .btn-secondary.active,.cyan-skin .btn-secondary:active,.cyan-skin .btn-secondary:focus{background-color:#2f7e8a!important}.cyan-skin .btn-secondary.dropdown-toggle{background-color:#45b0c0!important}.cyan-skin .btn-secondary.dropdown-toggle:focus,.cyan-skin .btn-secondary.dropdown-toggle:hover{background-color:#58b8c6!important}.cyan-skin .btn-default{background-color:#114861}.cyan-skin .btn-default:hover{background-color:#155877!important}.cyan-skin .btn-default.active,.cyan-skin .btn-default:active,.cyan-skin .btn-default:focus{background-color:#061820!important}.cyan-skin .btn-default.dropdown-toggle{background-color:#114861!important}.cyan-skin .btn-default.dropdown-toggle:focus,.cyan-skin .btn-default.dropdown-toggle:hover{background-color:#155877!important}.cyan-skin .card .btn-action{background:#114861}.cyan-skin .card .btn-action:focus,.cyan-skin .card .btn-action:hover{background-color:#155877!important}.cyan-skin .card .btn-action.active{background-color:#02080a!important}.cyan-skin input[type=email]:focus:not([readonly]),.cyan-skin input[type=password]:focus:not([readonly]),.cyan-skin input[type=text]:focus:not([readonly]),.cyan-skin textarea.md-textarea:focus:not([readonly]){border-color:#f0b247;-webkit-box-shadow:0 1px 0 0 #f0b247;box-shadow:0 1px 0 0 #f0b247}.cyan-skin input[type=checkbox]:checked+label:before{border-right:2px solid #f0b247;border-bottom:2px solid #f0b247}.cyan-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.cyan-skin input[type=checkbox].filled-in:checked+label:after{background-color:#f0b247;border-color:#f0b247}.cyan-skin .top-nav-collapse{background-color:#114861}.cyan-skin .carousel-multi-item .carousel-indicators li,.cyan-skin .carousel-multi-item .carousel-indicators li.active,.cyan-skin .carousel-multi-item .controls-top>a{background-color:#f0b247}.cyan-skin .card-header,.cyan-skin .form-header{background-color:#f1b650}.cyan-skin .spinner-primary-color,.cyan-skin .spinner-primary-color-only{border-color:#4fada7}.cyan-skin .pagination-primary-color .page-item.active .page-link,.cyan-skin .pagination-primary-color .page-item.active .page-link:focus,.cyan-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#4fada7;border-color:#4fada7}.cyan-skin .pagination-primary-color .page-link{color:#4fada7}.mdb-skin .gradient{background:#0e2135;background:-webkit-linear-gradient(315deg,#0e2135 0,#2c76b8 100%);background:linear-gradient(135deg,#0e2135 0,#2c76b8 100%)}.mdb-skin .primary-color,.mdb-skin .stepper li.active a .circle,.mdb-skin .stepper li.completed a .circle,.stepper li.active a .mdb-skin .circle,.stepper li.completed a .mdb-skin .circle{background-color:#33b5e5!important}.mdb-skin .navbar{background-color:#243a51;color:#fff}.mdb-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.mdb-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.mdb-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#1dade2}.mdb-skin .page-footer{background-color:#243a51}.mdb-skin .side-nav{background-color:#224562}.mdb-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.mdb-skin .side-nav .sn-avatar-wrapper img{border:3px solid #178ab4}.mdb-skin .side-nav .social a:hover .fa{color:#33b5e5!important;-webkit-transition:all .3s linear;transition:all .3s linear}.mdb-skin .side-nav .collapsible li{background-color:transparent}.mdb-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.mdb-skin .side-nav .collapsible li .collapsible-header.active,.mdb-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(72,198,255,.8)}.mdb-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.mdb-skin .side-nav .collapsible li .collapsible-body a:hover{color:#67d5ff}.mdb-skin .side-nav .fa{color:#fff}.mdb-skin .dropdown-content li:not(.disabled) span,.mdb-skin .md-form .prefix.active,.mdb-skin input[type=email]:focus:not([readonly])+label,.mdb-skin input[type=password]:focus:not([readonly])+label,.mdb-skin input[type=text]:focus:not([readonly])+label,.mdb-skin textarea.md-textarea:focus:not([readonly])+label{color:#33b5e5}.mdb-skin .side-nav .sidenav-bg.mask-strong:after,.mdb-skin .side-nav .sidenav-bg:after{background:rgba(13,36,60,.8)}.mdb-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(13,36,60,.65)}.mdb-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(13,36,60,.5)}.mdb-skin .btn-primary{background-color:#33b5e5}.mdb-skin .btn-primary:hover{background-color:#4abde8!important}.mdb-skin .btn-primary.active,.mdb-skin .btn-primary:active,.mdb-skin .btn-primary:focus{background-color:#178ab4!important}.mdb-skin .btn-primary.dropdown-toggle{background-color:#33b5e5!important}.mdb-skin .btn-primary.dropdown-toggle:focus,.mdb-skin .btn-primary.dropdown-toggle:hover{background-color:#4abde8!important}.mdb-skin .btn-secondary{background-color:#0e3d67}.mdb-skin .btn-secondary:hover{background-color:#114a7d!important}.mdb-skin .btn-secondary.active,.mdb-skin .btn-secondary:active,.mdb-skin .btn-secondary:focus{background-color:#051524!important}.mdb-skin .btn-secondary.dropdown-toggle{background-color:#0e3d67!important}.mdb-skin .btn-secondary.dropdown-toggle:focus,.mdb-skin .btn-secondary.dropdown-toggle:hover{background-color:#114a7d!important}.mdb-skin .btn-default{background-color:#1a6398}.mdb-skin .btn-default:hover{background-color:#1e71ae!important}.mdb-skin .btn-default.active,.mdb-skin .btn-default:active,.mdb-skin .btn-default:focus{background-color:#0f3857!important}.mdb-skin .btn-default.dropdown-toggle{background-color:#1a6398!important}.mdb-skin .btn-default.dropdown-toggle:focus,.mdb-skin .btn-default.dropdown-toggle:hover{background-color:#1e71ae!important}.mdb-skin .card .btn-action{background:#1a6398}.mdb-skin .card .btn-action:focus,.mdb-skin .card .btn-action:hover{background-color:#1e71ae!important}.mdb-skin .card .btn-action.active{background-color:#0b2a41!important}.mdb-skin input[type=email]:focus:not([readonly]),.mdb-skin input[type=password]:focus:not([readonly]),.mdb-skin input[type=text]:focus:not([readonly]),.mdb-skin textarea.md-textarea:focus:not([readonly]){border-color:#33b5e5;-webkit-box-shadow:0 1px 0 0 #33b5e5;box-shadow:0 1px 0 0 #33b5e5}.mdb-skin input[type=checkbox]:checked+label:before{border-right:2px solid #33b5e5;border-bottom:2px solid #33b5e5}.mdb-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.mdb-skin input[type=checkbox].filled-in:checked+label:after{background-color:#33b5e5;border-color:#33b5e5}.mdb-skin .top-nav-collapse,.mdb-skin-custom .navbar{background-color:#243a51}.mdb-skin .carousel-multi-item .carousel-indicators li,.mdb-skin .carousel-multi-item .carousel-indicators li.active,.mdb-skin .carousel-multi-item .controls-top>a{background-color:#33b5e5}.mdb-skin .card-header,.mdb-skin .form-header{background-color:#3cb8e6}.mdb-skin .spinner-primary-color,.mdb-skin .spinner-primary-color-only{border-color:#33b5e5}.mdb-skin .pagination-primary-color .page-item.active .page-link,.mdb-skin .pagination-primary-color .page-item.active .page-link:focus,.mdb-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#33b5e5;border-color:#33b5e5}.mdb-skin .pagination-primary-color .page-link{color:#33b5e5}.deep-purple-skin .gradient{background:#2e1f49;background:-webkit-linear-gradient(315deg,#2e1f49 0,#a47fe3 100%);background:linear-gradient(135deg,#2e1f49 0,#a47fe3 100%)}.deep-purple-skin .primary-color,.deep-purple-skin .stepper li.active a .circle,.deep-purple-skin .stepper li.completed a .circle,.stepper li.active a .deep-purple-skin .circle,.stepper li.completed a .deep-purple-skin .circle{background-color:#d0637c!important}.deep-purple-skin .navbar{background-color:#7f7e91;color:#fff}.deep-purple-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.deep-purple-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.deep-purple-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#9d6eed}.deep-purple-skin .page-footer{background-color:#7f7e91}.deep-purple-skin .side-nav{background-color:#372e5f}.deep-purple-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.deep-purple-skin .side-nav .sn-avatar-wrapper img{border:3px solid #7e41e8}.deep-purple-skin .side-nav .social a:hover .fa{color:#ac85f0!important;-webkit-transition:all .3s linear;transition:all .3s linear}.deep-purple-skin .side-nav .collapsible li{background-color:transparent}.deep-purple-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.deep-purple-skin .side-nav .collapsible li .collapsible-header.active,.deep-purple-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(176,139,240,.5)}.deep-purple-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.deep-purple-skin .side-nav .collapsible li .collapsible-body a:hover{color:#c9abfc}.deep-purple-skin .side-nav .fa{color:#fff}.deep-purple-skin .dropdown-content li:not(.disabled) span,.deep-purple-skin .md-form .prefix.active,.deep-purple-skin input[type=email]:focus:not([readonly])+label,.deep-purple-skin input[type=password]:focus:not([readonly])+label,.deep-purple-skin input[type=text]:focus:not([readonly])+label,.deep-purple-skin textarea.md-textarea:focus:not([readonly])+label{color:#ac85f0}.deep-purple-skin .side-nav .sidenav-bg.mask-strong:after,.deep-purple-skin .side-nav .sidenav-bg:after{background:rgba(36,9,56,.88)}.deep-purple-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(36,9,56,.65)}.deep-purple-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(36,9,56,.5)}.deep-purple-skin .btn-primary{background-color:#ac85f0}.deep-purple-skin .btn-primary:hover{background-color:#bb9cf3!important}.deep-purple-skin .btn-primary.active,.deep-purple-skin .btn-primary:active,.deep-purple-skin .btn-primary:focus{background-color:#7e41e8!important}.deep-purple-skin .btn-primary.dropdown-toggle{background-color:#ac85f0!important}.deep-purple-skin .btn-primary.dropdown-toggle:focus,.deep-purple-skin .btn-primary.dropdown-toggle:hover{background-color:#bb9cf3!important}.deep-purple-skin .btn-secondary{background-color:#6e4ca3}.deep-purple-skin .btn-secondary:hover{background-color:#7a58b1!important}.deep-purple-skin .btn-secondary.active,.deep-purple-skin .btn-secondary:active,.deep-purple-skin .btn-secondary:focus{background-color:#4b346f!important}.deep-purple-skin .btn-secondary.dropdown-toggle{background-color:#6e4ca3!important}.deep-purple-skin .btn-secondary.dropdown-toggle:focus,.deep-purple-skin .btn-secondary.dropdown-toggle:hover{background-color:#7a58b1!important}.deep-purple-skin .btn-default{background-color:#372e5f}.deep-purple-skin .btn-default:hover{background-color:#413670!important}.deep-purple-skin .btn-default.active,.deep-purple-skin .btn-default:active,.deep-purple-skin .btn-default:focus{background-color:#19152b!important}.deep-purple-skin .btn-default.dropdown-toggle{background-color:#372e5f!important}.deep-purple-skin .btn-default.dropdown-toggle:focus,.deep-purple-skin .btn-default.dropdown-toggle:hover{background-color:#413670!important}.deep-purple-skin .card .btn-action{background:#372e5f}.deep-purple-skin .card .btn-action:focus,.deep-purple-skin .card .btn-action:hover{background-color:#413670!important}.deep-purple-skin .card .btn-action.active{background-color:#0f0d1a!important}.deep-purple-skin input[type=email]:focus:not([readonly]),.deep-purple-skin input[type=password]:focus:not([readonly]),.deep-purple-skin input[type=text]:focus:not([readonly]),.deep-purple-skin textarea.md-textarea:focus:not([readonly]){border-color:#ac85f0;-webkit-box-shadow:0 1px 0 0 #ac85f0;box-shadow:0 1px 0 0 #ac85f0}.deep-purple-skin input[type=checkbox]:checked+label:before{border-right:2px solid #ac85f0;border-bottom:2px solid #ac85f0}.deep-purple-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.deep-purple-skin input[type=checkbox].filled-in:checked+label:after{background-color:#ac85f0;border-color:#ac85f0}.deep-purple-skin .top-nav-collapse{background-color:#7f7e91}.deep-purple-skin .carousel-multi-item .carousel-indicators li,.deep-purple-skin .carousel-multi-item .carousel-indicators li.active,.deep-purple-skin .carousel-multi-item .controls-top>a{background-color:#ac85f0}.deep-purple-skin .card-header,.deep-purple-skin .form-header{background-color:#b28ef1}.deep-purple-skin .spinner-primary-color,.deep-purple-skin .spinner-primary-color-only{border-color:#d0637c}.deep-purple-skin .pagination-primary-color .page-item.active .page-link,.deep-purple-skin .pagination-primary-color .page-item.active .page-link:focus,.deep-purple-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#d0637c;border-color:#d0637c}.deep-purple-skin .pagination-primary-color .page-link{color:#d0637c}.navy-blue-skin .gradient{background:#222735;background:-webkit-linear-gradient(315deg,#222735 0,#4f68a6 100%);background:linear-gradient(135deg,#222735 0,#4f68a6 100%)}.navy-blue-skin .primary-color,.navy-blue-skin .stepper li.active a .circle,.navy-blue-skin .stepper li.completed a .circle,.stepper li.active a .navy-blue-skin .circle,.stepper li.completed a .navy-blue-skin .circle{background-color:#309e9e!important}.navy-blue-skin .navbar{background-color:#353b50;color:#fff}.navy-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.navy-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.navy-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#36b6b6}.navy-blue-skin .page-footer{background-color:#353b50}.navy-blue-skin .side-nav{background-color:#4c5678}.navy-blue-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.navy-blue-skin .side-nav .sn-avatar-wrapper img{border:3px solid #2b8f8f}.navy-blue-skin .side-nav .social a:hover .fa{color:#40c6c6!important;-webkit-transition:all .3s linear;transition:all .3s linear}.navy-blue-skin .side-nav .collapsible li{background-color:transparent}.navy-blue-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.navy-blue-skin .side-nav .collapsible li .collapsible-header.active,.navy-blue-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(37,207,207,.8)}.navy-blue-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.navy-blue-skin .side-nav .collapsible li .collapsible-body a:hover{color:#40c6c6}.navy-blue-skin .side-nav .fa{color:#fff}.navy-blue-skin .dropdown-content li:not(.disabled) span,.navy-blue-skin .md-form .prefix.active,.navy-blue-skin input[type=email]:focus:not([readonly])+label,.navy-blue-skin input[type=password]:focus:not([readonly])+label,.navy-blue-skin input[type=text]:focus:not([readonly])+label,.navy-blue-skin textarea.md-textarea:focus:not([readonly])+label{color:#40c6c6}.navy-blue-skin .side-nav .sidenav-bg.mask-strong:after,.navy-blue-skin .side-nav .sidenav-bg:after{background:rgba(14,15,32,.8)}.navy-blue-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(14,15,32,.65)}.navy-blue-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(14,15,32,.5)}.navy-blue-skin .btn-primary{background-color:#40c6c6}.navy-blue-skin .btn-primary:hover{background-color:#54cccc!important}.navy-blue-skin .btn-primary.active,.navy-blue-skin .btn-primary:active,.navy-blue-skin .btn-primary:focus{background-color:#2b8f8f!important}.navy-blue-skin .btn-primary.dropdown-toggle{background-color:#40c6c6!important}.navy-blue-skin .btn-primary.dropdown-toggle:focus,.navy-blue-skin .btn-primary.dropdown-toggle:hover{background-color:#54cccc!important}.navy-blue-skin .btn-secondary{background-color:#7e51b4}.navy-blue-skin .btn-secondary:hover{background-color:#8b63bc!important}.navy-blue-skin .btn-secondary.active,.navy-blue-skin .btn-secondary:active,.navy-blue-skin .btn-secondary:focus{background-color:#593881!important}.navy-blue-skin .btn-secondary.dropdown-toggle{background-color:#7e51b4!important}.navy-blue-skin .btn-secondary.dropdown-toggle:focus,.navy-blue-skin .btn-secondary.dropdown-toggle:hover{background-color:#8b63bc!important}.navy-blue-skin .btn-default{background-color:#293756}.navy-blue-skin .btn-default:hover{background-color:#314267!important}.navy-blue-skin .btn-default.active,.navy-blue-skin .btn-default:active,.navy-blue-skin .btn-default:focus{background-color:#101622!important}.navy-blue-skin .btn-default.dropdown-toggle{background-color:#293756!important}.navy-blue-skin .btn-default.dropdown-toggle:focus,.navy-blue-skin .btn-default.dropdown-toggle:hover{background-color:#314267!important}.navy-blue-skin .card .btn-action{background:#293756}.navy-blue-skin .card .btn-action:focus,.navy-blue-skin .card .btn-action:hover{background-color:#314267!important}.navy-blue-skin .card .btn-action.active{background-color:#080b11!important}.navy-blue-skin input[type=email]:focus:not([readonly]),.navy-blue-skin input[type=password]:focus:not([readonly]),.navy-blue-skin input[type=text]:focus:not([readonly]),.navy-blue-skin textarea.md-textarea:focus:not([readonly]){border-color:#40c6c6;-webkit-box-shadow:0 1px 0 0 #40c6c6;box-shadow:0 1px 0 0 #40c6c6}.navy-blue-skin input[type=checkbox]:checked+label:before{border-right:2px solid #40c6c6;border-bottom:2px solid #40c6c6}.navy-blue-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.navy-blue-skin input[type=checkbox].filled-in:checked+label:after{background-color:#40c6c6;border-color:#40c6c6}.navy-blue-skin .top-nav-collapse{background-color:#353b50}.navy-blue-skin .carousel-multi-item .carousel-indicators li,.navy-blue-skin .carousel-multi-item .carousel-indicators li.active,.navy-blue-skin .carousel-multi-item .controls-top>a{background-color:#40c6c6}.navy-blue-skin .card-header,.navy-blue-skin .form-header{background-color:#48c8c8}.navy-blue-skin .spinner-primary-color,.navy-blue-skin .spinner-primary-color-only{border-color:#309e9e}.navy-blue-skin .pagination-primary-color .page-item.active .page-link,.navy-blue-skin .pagination-primary-color .page-item.active .page-link:focus,.navy-blue-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#309e9e;border-color:#309e9e}.navy-blue-skin .pagination-primary-color .page-link{color:#309e9e}.pink-skin .gradient{background:#812b5a;background:-webkit-linear-gradient(315deg,#812b5a 0,#f28cc0 100%);background:linear-gradient(135deg,#812b5a 0,#f28cc0 100%)}.pink-skin .primary-color,.pink-skin .stepper li.active a .circle,.pink-skin .stepper li.completed a .circle,.stepper li.active a .pink-skin .circle,.stepper li.completed a .pink-skin .circle{background-color:#bd5d70!important}.pink-skin .navbar{background-color:#535466;color:#fff}.pink-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.pink-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.pink-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#9192a2}.pink-skin .page-footer{background-color:#535466}.pink-skin .side-nav{background-color:#aa5077}.pink-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.pink-skin .side-nav .sn-avatar-wrapper img{border:3px solid #76778b}.pink-skin .side-nav .social a:hover .fa{color:#9fa0ae!important;-webkit-transition:all .3s linear;transition:all .3s linear}.pink-skin .side-nav .collapsible li{background-color:transparent}.pink-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.pink-skin .side-nav .collapsible li .collapsible-header.active,.pink-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(0,0,0,.4)}.pink-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.pink-skin .side-nav .collapsible li .collapsible-body a:hover{color:#ffb0e6}.pink-skin .side-nav .fa{color:#fff}.pink-skin .dropdown-content li:not(.disabled) span,.pink-skin .md-form .prefix.active,.pink-skin input[type=email]:focus:not([readonly])+label,.pink-skin input[type=password]:focus:not([readonly])+label,.pink-skin input[type=text]:focus:not([readonly])+label,.pink-skin textarea.md-textarea:focus:not([readonly])+label{color:#9fa0ae}.pink-skin .side-nav .sidenav-bg.mask-strong:after,.pink-skin .side-nav .sidenav-bg:after{background:rgba(152,47,88,.8)}.pink-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(152,47,88,.65)}.pink-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(152,47,88,.5)}.pink-skin .btn-primary{background-color:#601f39}.pink-skin .btn-primary:hover{background-color:#732544!important}.pink-skin .btn-primary.active,.pink-skin .btn-primary:active,.pink-skin .btn-primary:focus{background-color:#260c17!important}.pink-skin .btn-primary.dropdown-toggle{background-color:#601f39!important}.pink-skin .btn-primary.dropdown-toggle:focus,.pink-skin .btn-primary.dropdown-toggle:hover{background-color:#732544!important}.pink-skin .btn-secondary{background-color:#e7649d}.pink-skin .btn-secondary:hover{background-color:#ea7aab!important}.pink-skin .btn-secondary.active,.pink-skin .btn-secondary:active,.pink-skin .btn-secondary:focus{background-color:#dc2273!important}.pink-skin .btn-secondary.dropdown-toggle{background-color:#e7649d!important}.pink-skin .btn-secondary.dropdown-toggle:focus,.pink-skin .btn-secondary.dropdown-toggle:hover{background-color:#ea7aab!important}.pink-skin .btn-default{background-color:#535466}.pink-skin .btn-default:hover{background-color:#5e6074!important}.pink-skin .btn-default.active,.pink-skin .btn-default:active,.pink-skin .btn-default:focus{background-color:#31313c!important}.pink-skin .btn-default.dropdown-toggle{background-color:#535466!important}.pink-skin .btn-default.dropdown-toggle:focus,.pink-skin .btn-default.dropdown-toggle:hover{background-color:#5e6074!important}.pink-skin .card .btn-action{background:#535466}.pink-skin .card .btn-action:focus,.pink-skin .card .btn-action:hover{background-color:#5e6074!important}.pink-skin .card .btn-action.active{background-color:#25262e!important}.pink-skin input[type=email]:focus:not([readonly]),.pink-skin input[type=password]:focus:not([readonly]),.pink-skin input[type=text]:focus:not([readonly]),.pink-skin textarea.md-textarea:focus:not([readonly]){border-color:#9fa0ae;-webkit-box-shadow:0 1px 0 0 #9fa0ae;box-shadow:0 1px 0 0 #9fa0ae}.pink-skin input[type=checkbox]:checked+label:before{border-right:2px solid #9fa0ae;border-bottom:2px solid #9fa0ae}.pink-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.pink-skin input[type=checkbox].filled-in:checked+label:after{background-color:#9fa0ae;border-color:#9fa0ae}.pink-skin .top-nav-collapse{background-color:#535466}.pink-skin .carousel-multi-item .carousel-indicators li,.pink-skin .carousel-multi-item .carousel-indicators li.active,.pink-skin .carousel-multi-item .controls-top>a{background-color:#9fa0ae}.pink-skin .card-header,.pink-skin .form-header{background-color:#a5a5b3}.pink-skin .spinner-primary-color,.pink-skin .spinner-primary-color-only{border-color:#bd5d70}.pink-skin .pagination-primary-color .page-item.active .page-link,.pink-skin .pagination-primary-color .page-item.active .page-link:focus,.pink-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#bd5d70;border-color:#bd5d70}.pink-skin .pagination-primary-color .page-link{color:#bd5d70}.indigo-skin .gradient{background:#272d6e;background:-webkit-linear-gradient(315deg,#272d6e 0,#90a8ff 100%);background:linear-gradient(135deg,#272d6e 0,#90a8ff 100%)}.indigo-skin .primary-color,.indigo-skin .stepper li.active a .circle,.indigo-skin .stepper li.completed a .circle,.stepper li.active a .indigo-skin .circle,.stepper li.completed a .indigo-skin .circle{background-color:#7f82c5!important}.indigo-skin .navbar{background-color:#9095aa;color:#fff}.indigo-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.indigo-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.indigo-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#fd4d79}.indigo-skin .page-footer{background-color:#9095aa}.indigo-skin .side-nav{background-color:#404f9f}.indigo-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.indigo-skin .side-nav .sn-avatar-wrapper img{border:3px solid #fc1a53}.indigo-skin .side-nav .social a:hover .fa{color:#fd668c!important;-webkit-transition:all .3s linear;transition:all .3s linear}.indigo-skin .side-nav .collapsible li{background-color:transparent}.indigo-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.indigo-skin .side-nav .collapsible li .collapsible-header.active,.indigo-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(250,80,121,.8)}.indigo-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.indigo-skin .side-nav .collapsible li .collapsible-body a:hover{color:#ff89ac}.indigo-skin .side-nav .fa{color:#fff}.indigo-skin .dropdown-content li:not(.disabled) span,.indigo-skin .md-form .prefix.active,.indigo-skin input[type=email]:focus:not([readonly])+label,.indigo-skin input[type=password]:focus:not([readonly])+label,.indigo-skin input[type=text]:focus:not([readonly])+label,.indigo-skin textarea.md-textarea:focus:not([readonly])+label{color:#fd668c}.indigo-skin .side-nav .sidenav-bg.mask-strong:after,.indigo-skin .side-nav .sidenav-bg:after{background:rgba(35,65,134,.8)}.indigo-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(35,65,134,.65)}.indigo-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(35,65,134,.5)}.indigo-skin .btn-primary{background-color:#fd668c}.indigo-skin .btn-primary:hover{background-color:#fd7f9f!important}.indigo-skin .btn-primary.active,.indigo-skin .btn-primary:active,.indigo-skin .btn-primary:focus{background-color:#fc1a53!important}.indigo-skin .btn-primary.dropdown-toggle{background-color:#fd668c!important}.indigo-skin .btn-primary.dropdown-toggle:focus,.indigo-skin .btn-primary.dropdown-toggle:hover{background-color:#fd7f9f!important}.indigo-skin .btn-secondary{background-color:#3c61ae}.indigo-skin .btn-secondary:hover{background-color:#456cbf!important}.indigo-skin .btn-secondary.active,.indigo-skin .btn-secondary:active,.indigo-skin .btn-secondary:focus{background-color:#284175!important}.indigo-skin .btn-secondary.dropdown-toggle{background-color:#3c61ae!important}.indigo-skin .btn-secondary.dropdown-toggle:focus,.indigo-skin .btn-secondary.dropdown-toggle:hover{background-color:#456cbf!important}.indigo-skin .btn-default{background-color:#9095aa}.indigo-skin .btn-default:hover{background-color:#9ea3b5!important}.indigo-skin .btn-default.active,.indigo-skin .btn-default:active,.indigo-skin .btn-default:focus{background-color:#676d87!important}.indigo-skin .btn-default.dropdown-toggle{background-color:#9095aa!important}.indigo-skin .btn-default.dropdown-toggle:focus,.indigo-skin .btn-default.dropdown-toggle:hover{background-color:#9ea3b5!important}.indigo-skin .card .btn-action{background:#9095aa}.indigo-skin .card .btn-action:focus,.indigo-skin .card .btn-action:hover{background-color:#9ea3b5!important}.indigo-skin .card .btn-action.active{background-color:#5c6178!important}.indigo-skin input[type=email]:focus:not([readonly]),.indigo-skin input[type=password]:focus:not([readonly]),.indigo-skin input[type=text]:focus:not([readonly]),.indigo-skin textarea.md-textarea:focus:not([readonly]){border-color:#fd668c;-webkit-box-shadow:0 1px 0 0 #fd668c;box-shadow:0 1px 0 0 #fd668c}.indigo-skin input[type=checkbox]:checked+label:before{border-right:2px solid #fd668c;border-bottom:2px solid #fd668c}.indigo-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.indigo-skin input[type=checkbox].filled-in:checked+label:after{background-color:#fd668c;border-color:#fd668c}.indigo-skin .top-nav-collapse{background-color:#9095aa}.indigo-skin .carousel-multi-item .carousel-indicators li,.indigo-skin .carousel-multi-item .carousel-indicators li.active,.indigo-skin .carousel-multi-item .controls-top>a{background-color:#fd668c}.indigo-skin .card-header,.indigo-skin .form-header{background-color:#fd7094}.indigo-skin .spinner-primary-color,.indigo-skin .spinner-primary-color-only{border-color:#7f82c5}.indigo-skin .pagination-primary-color .page-item.active .page-link,.indigo-skin .pagination-primary-color .page-item.active .page-link:focus,.indigo-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#7f82c5;border-color:#7f82c5}.indigo-skin .pagination-primary-color .page-link{color:#7f82c5}.light-blue-skin .gradient{background:#69adf4;background:-webkit-linear-gradient(315deg,#69adf4 0,#69adf4 100%);background:linear-gradient(135deg,#69adf4 0,#69adf4 100%)}.light-blue-skin .primary-color,.light-blue-skin .stepper li.active a .circle,.light-blue-skin .stepper li.completed a .circle,.stepper li.active a .light-blue-skin .circle,.stepper li.completed a .light-blue-skin .circle{background-color:#3d799c!important}.light-blue-skin .navbar{background-color:#3f5c80;color:#fff}.light-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.light-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.light-blue-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#a5b6be}.light-blue-skin .page-footer{background-color:#3f5c80}.light-blue-skin .side-nav{background-color:#6a9ed3}.light-blue-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.light-blue-skin .side-nav .sn-avatar-wrapper img{border:3px solid #889ea9}.light-blue-skin .side-nav .social a:hover .fa{color:#b4c2c9!important;-webkit-transition:all .3s linear;transition:all .3s linear}.light-blue-skin .side-nav .collapsible li{background-color:transparent}.light-blue-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.light-blue-skin .side-nav .collapsible li .collapsible-header.active,.light-blue-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(29,54,86,.6)}.light-blue-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.light-blue-skin .side-nav .collapsible li .collapsible-body a:hover{color:#aadeff}.light-blue-skin .side-nav .fa{color:#fff}.light-blue-skin .dropdown-content li:not(.disabled) span,.light-blue-skin .md-form .prefix.active,.light-blue-skin input[type=email]:focus:not([readonly])+label,.light-blue-skin input[type=password]:focus:not([readonly])+label,.light-blue-skin input[type=text]:focus:not([readonly])+label,.light-blue-skin textarea.md-textarea:focus:not([readonly])+label{color:#b4c2c9}.light-blue-skin .side-nav .sidenav-bg.mask-strong:after,.light-blue-skin .side-nav .sidenav-bg:after{background:rgba(87,134,180,.8)}.light-blue-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(87,134,180,.65)}.light-blue-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(87,134,180,.5)}.light-blue-skin .btn-primary{background-color:#ff4a67}.light-blue-skin .btn-primary:hover{background-color:#ff647c!important}.light-blue-skin .btn-primary.active,.light-blue-skin .btn-primary:active,.light-blue-skin .btn-primary:focus{background-color:#fd0028!important}.light-blue-skin .btn-primary.dropdown-toggle{background-color:#ff4a67!important}.light-blue-skin .btn-primary.dropdown-toggle:focus,.light-blue-skin .btn-primary.dropdown-toggle:hover{background-color:#ff647c!important}.light-blue-skin .btn-secondary{background-color:#64c3f0}.light-blue-skin .btn-secondary:hover{background-color:#7bccf2!important}.light-blue-skin .btn-secondary.active,.light-blue-skin .btn-secondary:active,.light-blue-skin .btn-secondary:focus{background-color:#1ea8e9!important}.light-blue-skin .btn-secondary.dropdown-toggle{background-color:#64c3f0!important}.light-blue-skin .btn-secondary.dropdown-toggle:focus,.light-blue-skin .btn-secondary.dropdown-toggle:hover{background-color:#7bccf2!important}.light-blue-skin .btn-default{background-color:#2d486a}.light-blue-skin .btn-default:hover{background-color:#35547c!important}.light-blue-skin .btn-default.active,.light-blue-skin .btn-default:active,.light-blue-skin .btn-default:focus{background-color:#162434!important}.light-blue-skin .btn-default.dropdown-toggle{background-color:#2d486a!important}.light-blue-skin .btn-default.dropdown-toggle:focus,.light-blue-skin .btn-default.dropdown-toggle:hover{background-color:#35547c!important}.light-blue-skin .card .btn-action{background:#2d486a}.light-blue-skin .card .btn-action:focus,.light-blue-skin .card .btn-action:hover{background-color:#35547c!important}.light-blue-skin .card .btn-action.active{background-color:#0f1722!important}.light-blue-skin input[type=email]:focus:not([readonly]),.light-blue-skin input[type=password]:focus:not([readonly]),.light-blue-skin input[type=text]:focus:not([readonly]),.light-blue-skin textarea.md-textarea:focus:not([readonly]){border-color:#b4c2c9;-webkit-box-shadow:0 1px 0 0 #b4c2c9;box-shadow:0 1px 0 0 #b4c2c9}.light-blue-skin input[type=checkbox]:checked+label:before{border-right:2px solid #b4c2c9;border-bottom:2px solid #b4c2c9}.light-blue-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.light-blue-skin input[type=checkbox].filled-in:checked+label:after{background-color:#b4c2c9;border-color:#b4c2c9}.light-blue-skin .top-nav-collapse{background-color:#3f5c80}.light-blue-skin .carousel-multi-item .carousel-indicators li,.light-blue-skin .carousel-multi-item .carousel-indicators li.active,.light-blue-skin .carousel-multi-item .controls-top>a{background-color:#b4c2c9}.light-blue-skin .card-header,.light-blue-skin .form-header{background-color:#bac7cd}.light-blue-skin .spinner-primary-color,.light-blue-skin .spinner-primary-color-only{border-color:#3d799c}.light-blue-skin .pagination-primary-color .page-item.active .page-link,.light-blue-skin .pagination-primary-color .page-item.active .page-link:focus,.light-blue-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#3d799c;border-color:#3d799c}.light-blue-skin .pagination-primary-color .page-link{color:#3d799c}.grey-skin .gradient{background:#383838;background:-webkit-linear-gradient(315deg,#383838 0,#a5a4a4 100%);background:linear-gradient(135deg,#383838 0,#a5a4a4 100%)}.grey-skin .primary-color,.grey-skin .stepper li.active a .circle,.grey-skin .stepper li.completed a .circle,.stepper li.active a .grey-skin .circle,.stepper li.completed a .grey-skin .circle{background-color:#2b2b2b!important}.grey-skin .navbar{background-color:#44474b;color:#fff}.grey-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.grey-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.grey-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#5eb7ee}.grey-skin .page-footer{background-color:#44474b}.grey-skin .side-nav{background-color:#a5a4a4}.grey-skin .side-nav .logo-wrapper>div{background-color:transparent!important}.grey-skin .side-nav .sn-avatar-wrapper img{border:3px solid #30a2e9}.grey-skin .side-nav .social a:hover .fa{color:#75c1f0!important;-webkit-transition:all .3s linear;transition:all .3s linear}.grey-skin .side-nav .collapsible li{background-color:transparent}.grey-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.grey-skin .side-nav .collapsible li .collapsible-header.active,.grey-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(0,0,0,.4)}.grey-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.grey-skin .side-nav .collapsible li .collapsible-body a:hover{color:#afdffc}.grey-skin .side-nav .fa{color:#fff}.grey-skin .dropdown-content li:not(.disabled) span,.grey-skin .md-form .prefix.active,.grey-skin input[type=email]:focus:not([readonly])+label,.grey-skin input[type=password]:focus:not([readonly])+label,.grey-skin input[type=text]:focus:not([readonly])+label,.grey-skin textarea.md-textarea:focus:not([readonly])+label{color:#75c1f0}.grey-skin .side-nav .sidenav-bg.mask-strong:after,.grey-skin .side-nav .sidenav-bg:after{background:rgba(121,121,121,.8)}.grey-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(121,121,121,.65)}.grey-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(121,121,121,.5)}.grey-skin .btn-primary{background-color:#46aded}.grey-skin .btn-primary:hover{background-color:#5db7ef!important}.grey-skin .btn-primary.active,.grey-skin .btn-primary:active,.grey-skin .btn-primary:focus{background-color:#1489d2!important}.grey-skin .btn-primary.dropdown-toggle{background-color:#46aded!important}.grey-skin .btn-primary.dropdown-toggle:focus,.grey-skin .btn-primary.dropdown-toggle:hover{background-color:#5db7ef!important}.grey-skin .btn-secondary{background-color:#7d8488}.grey-skin .btn-secondary:hover{background-color:#8a9194!important}.grey-skin .btn-secondary.active,.grey-skin .btn-secondary:active,.grey-skin .btn-secondary:focus{background-color:#585d60!important}.grey-skin .btn-secondary.dropdown-toggle{background-color:#7d8488!important}.grey-skin .btn-secondary.dropdown-toggle:focus,.grey-skin .btn-secondary.dropdown-toggle:hover{background-color:#8a9194!important}.grey-skin .btn-default{background-color:#353637}.grey-skin .btn-default:hover{background-color:#424344!important}.grey-skin .btn-default.active,.grey-skin .btn-default:active,.grey-skin .btn-default:focus{background-color:#0f1010!important}.grey-skin .btn-default.dropdown-toggle{background-color:#353637!important}.grey-skin .btn-default.dropdown-toggle:focus,.grey-skin .btn-default.dropdown-toggle:hover{background-color:#424344!important}.grey-skin .card .btn-action{background:#353637}.grey-skin .card .btn-action:focus,.grey-skin .card .btn-action:hover{background-color:#424344!important}.grey-skin .card .btn-action.active{background-color:#030303!important}.grey-skin input[type=email]:focus:not([readonly]),.grey-skin input[type=password]:focus:not([readonly]),.grey-skin input[type=text]:focus:not([readonly]),.grey-skin textarea.md-textarea:focus:not([readonly]){border-color:#75c1f0;-webkit-box-shadow:0 1px 0 0 #75c1f0;box-shadow:0 1px 0 0 #75c1f0}.grey-skin input[type=checkbox]:checked+label:before{border-right:2px solid #75c1f0;border-bottom:2px solid #75c1f0}.grey-skin input[type=checkbox].filled-in:checked+label:before{border-right:2px solid #fff;border-bottom:2px solid #fff}.grey-skin input[type=checkbox].filled-in:checked+label:after{background-color:#75c1f0;border-color:#75c1f0}.grey-skin .top-nav-collapse{background-color:#44474b}.grey-skin .carousel-multi-item .carousel-indicators li,.grey-skin .carousel-multi-item .carousel-indicators li.active,.grey-skin .carousel-multi-item .controls-top>a{background-color:#75c1f0}.grey-skin .card-header,.grey-skin .form-header{background-color:#7ec5f1}.grey-skin .spinner-primary-color,.grey-skin .spinner-primary-color-only{border-color:#2b2b2b}.grey-skin .pagination-primary-color .page-item.active .page-link,.grey-skin .pagination-primary-color .page-item.active .page-link:focus,.grey-skin .pagination-primary-color .page-item.active .page-link:hover{color:#fff;background-color:#2b2b2b;border-color:#2b2b2b}.grey-skin .pagination-primary-color .page-link{color:#2b2b2b}.picker__input{cursor:default}.picker{font-size:16px;text-align:center;line-height:1.2;color:#000;position:absolute;z-index:10000;user-select:none}.picker .picker__holder{width:100%;overflow-y:auto;overflow-scrolling:touch;position:fixed;-webkit-transition:background .15s ease-out,top 0s .15s;transition:background .15s ease-out,top 0s .15s;-webkit-backface-visibility:hidden;backface-visibility:hidden}.picker .picker__frame,.picker .picker__holder{bottom:0;left:0;right:0;top:100%}.picker .picker__frame{position:absolute;margin:0 auto;min-width:256px;max-width:325px;width:300px;max-height:350px;filter:alpha(opacity=0);opacity:0;-webkit-transition:all .15s ease-out;transition:all .15s ease-out}@media (min-height:40.125em){.picker .picker__frame{margin-bottom:7.5%}}.picker .picker__frame .picker__wrap{display:table;width:100%;height:100%}@media (min-height:28.875em){.picker .picker__frame{overflow:visible;top:auto;bottom:-100%;max-height:80%}.picker .picker__frame .picker__wrap{display:block}}.picker .picker__box{background:#fff;display:table-cell}@media (min-height:28.875em){.picker .picker__box{display:block;border:1px solid #777;border-top-color:#898989;border-bottom-width:0;border-radius:5px 5px 0 0;-webkit-box-shadow:0 12px 36px 16px rgba(0,0,0,.24);box-shadow:0 12px 36px 16px rgba(0,0,0,.24)}}.picker--opened .picker__holder{top:0;zoom:1;background:rgba(0,0,0,.32);-webkit-transition:background .15s ease-out;transition:background .15s ease-out}.picker--opened .picker__frame{top:0;filter:alpha(opacity=100);opacity:1}@media (min-height:35.875em){.picker--opened .picker__frame{top:10%;bottom:auto}}.picker__input.picker__input--active{border-color:#E3F2FD}.picker__list{padding:.75em 0 4.2em;margin:0}.picker__list-item{border-bottom:1px solid #ddd;border-top:1px solid #ddd;margin-bottom:-1px;position:relative;padding:.75em 1.25em}.picker__list-item--highlighted,.picker__list-item:hover{border-color:#0089ec;z-index:10}@media (min-height:46.75em){.picker__list-item{padding:.5em 1em}}.picker__list-item:hover{cursor:pointer;background:#b1dcfb}.picker--focused .picker__list-item--highlighted,.picker__list-item--highlighted:hover{cursor:pointer;color:#000;background:#b1dcfb}.picker--focused .picker__list-item--selected,.picker__list-item--selected,.picker__list-item--selected:hover{background:#0089ec;z-index:10}.picker--focused .picker__list-item--disabled,.picker__list-item--disabled,.picker__list-item--disabled:hover{background:#f5f5f5;color:#ddd;cursor:default;border-color:#ddd;z-index:auto}.picker--time .picker__button--clear{display:block;width:80%;margin:1em auto 0;padding:1em 1.25em;background:0 0;border:0;font-weight:500;font-size:.67em;text-align:center;text-transform:uppercase;color:#666}.picker--time .picker__button--clear:focus,.picker--time .picker__button--clear:hover{color:#000;background:#e20;border-color:#e20;cursor:pointer;outline:0}.picker--time .picker__button--clear:before{top:-.25em;color:#666;font-size:1.25em;font-weight:700}.picker--time .picker__frame{min-width:256px;max-width:320px}.picker--time .picker__box{font-size:1em;background:#f2f2f2;padding:0}@media (min-height:40.125em){.picker--time .picker__box{margin-bottom:5em}}.picker__date-display{text-align:center;background-color:#4285F4;padding-bottom:15px;font-weight:300;margin-bottom:1rem}.picker__date-display .clockpicker-display{display:inline-block;margin:auto;height:85px;font-size:70px;padding:10px 10px 0;color:#b2dfdb}.picker__date-display .clockpicker-display .clockpicker-display-column #click-am.text-primary,.picker__date-display .clockpicker-display .clockpicker-display-column #click-pm.text-primary,.picker__date-display .clockpicker-display .clockpicker-display-column .clockpicker-span-hours.text-primary,.picker__date-display .clockpicker-display .clockpicker-display-column .clockpicker-span-minutes.text-primary{-webkit-animation-name:pulse;animation-name:pulse}.picker__date-display .clockpicker-display .clockpicker-display-column #click-am,.picker__date-display .clockpicker-display .clockpicker-display-column #click-pm{cursor:pointer}.picker__date-display .clockpicker-display .clockpicker-display-am-pm{padding-left:5px;vertical-align:bottom;height:85px}.picker__date-display .clockpicker-display .clockpicker-display-am-pm .clockpicker-span-am-pm{display:inline-block;font-size:23px;line-height:25px;color:#b2dfdb}.picker__date-display .clockpicker-display .clockpicker-span-hours,.picker__date-display .clockpicker-display .clockpicker-span-minutes{-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-transition:color .5s;transition:color .5s;cursor:pointer}.clockpicker-display{text-align:center;vertical-align:middle;display:inline-block;margin:auto;height:85px;font-size:70px;padding:10px 10px 0;color:#b2dfdb}.clockpicker-display .clockpicker-display-column #click-am.text-primary,.clockpicker-display .clockpicker-display-column #click-pm.text-primary,.clockpicker-display .clockpicker-display-column .clockpicker-span-hours.text-primary,.clockpicker-display .clockpicker-display-column .clockpicker-span-minutes.text-primary{-webkit-animation-name:pulse;animation-name:pulse}.clockpicker-display .clockpicker-display-column #click-am,.clockpicker-display .clockpicker-display-column #click-pm{cursor:pointer}.clockpicker-display .clockpicker-display-am-pm{padding-left:5px;vertical-align:bottom;height:85px}.clockpicker-display .clockpicker-display-am-pm .clockpicker-span-am-pm{display:inline-block;font-size:23px;line-height:25px;color:#b2dfdb}.clockpicker-display .clockpicker-span-hours,.clockpicker-display .clockpicker-span-minutes{-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-transition:color .5s;transition:color .5s;cursor:pointer}@keyframes pulse{from,to{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}}.clockpicker-moving{cursor:move}.clockpicker-plate{background-color:#eee;border-radius:50%;width:270px;height:270px;overflow:visible;position:relative;margin:20px auto auto;user-select:none}.clockpicker-plate .clockpicker-canvas,.clockpicker-plate .clockpicker-dial{width:270px;height:270px;position:absolute;left:-1px;top:-1px}.clockpicker-plate .clockpicker-dial{-webkit-transition:opacity 350ms,-webkit-transform 350ms;transition:opacity 350ms,-webkit-transform 350ms;transition:transform 350ms,opacity 350ms;transition:transform 350ms,opacity 350ms,-webkit-transform 350ms}.clockpicker-plate .clockpicker-dial .clockpicker-tick{border-radius:50%;color:#666;line-height:40px;text-align:center;width:40px;height:40px;position:absolute;cursor:pointer;-webkit-transition:background-color .3s;transition:background-color .3s;background-color:rgba(0,150,136,0)}.clockpicker-plate .clockpicker-dial .clockpicker-tick.active,.clockpicker-plate .clockpicker-dial .clockpicker-tick:hover{background-color:rgba(0,150,136,.25)}.clockpicker-plate .clockpicker-minutes{visibility:hidden}.clockpicker-plate .clockpicker-dial-out{opacity:0}.clockpicker-plate .clockpicker-hours.clockpicker-dial-out{-webkit-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);transform:scale(1.2,1.2)}.clockpicker-plate .clockpicker-minutes.clockpicker-dial-out{-webkit-transform:scale(.8,.8);-ms-transform:scale(.8,.8);transform:scale(.8,.8)}.clockpicker-canvas{-webkit-transition:opacity .3s;transition:opacity .3s}.clockpicker-canvas line{stroke:rgba(0,150,136,.25);stroke-width:1}.clockpicker-canvas-out{opacity:.25}.clockpicker-canvas-bearing{stroke:none;fill:rgba(0,77,64,.75)}.clockpicker-canvas-fg{stroke:none;fill:rgba(0,77,64,0)}.clockpicker-canvas-fg.active{fill:rgba(0,77,64,.5)}.clockpicker-canvas-bg,.clockpicker-canvas-bg-trans{fill:rgba(0,150,136,.25)}.clockpicker-canvas-bg{stroke:none}.clockpicker-am-pm-block{margin-top:-10px;width:100%;height:50px}.clockpicker-am-pm-block .clockpicker-button.am-button{height:45px;width:45px;float:left}.clockpicker-am-pm-block .clockpicker-button.pm-button{height:45px;width:45px;float:right}.btn-floating.btn-flat{padding:0;background:#4285F4}.btn-floating.btn-flat:hover{-webkit-box-shadow:none;box-shadow:none}.btn-floating.btn-flat:focus,.btn-floating.btn-flat:hover{background-color:#5a95f5!important}.btn-floating.btn-flat.active{background-color:#0b51c5!important}.picker__footer .clockpicker-button{margin:15px auto auto;background-color:transparent;text-transform:uppercase}.picker__footer .clockpicker-button:focus{background-color:transparent}.picker__footer .clockpicker-button:active{background-color:rgba(0,150,136,.25)}.darktheme .picker__box{background-color:#212121}.darktheme .picker__box .picker__calendar-container .clockpicker-plate,.darktheme .picker__box .picker__date-display{background-color:transparent}.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-tick{background-color:rgba(255,64,129,0)}.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-tick.active,.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-tick:hover,.darktheme .picker__box .picker__footer .clockpicker-button:active{background-color:rgba(255,64,129,.25)}.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas line{stroke:rgba(255,64,129,.25)}.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-bearing{fill:#fff}.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-fg{fill:rgba(255,64,129,0)}.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-fg.active{fill:rgba(255,64,129,.5)}.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-bg,.darktheme .picker__box .picker__calendar-container .clockpicker-plate .clockpicker-canvas-bg-trans{fill:rgba(255,64,129,.25)}.picker__box{padding:0;border-radius:2px;overflow:hidden}.picker__box .picker__header{text-align:center;position:relative;margin-bottom:20px}.picker__box .picker__header select{display:inline-block!important}.picker__box .picker__header .picker__date-display{text-align:center;background-color:#4285F4;padding-bottom:15px;font-weight:300;margin-bottom:1rem}.picker__box .picker__header .picker__date-display .picker__weekday-display{background-color:#206ff2;padding:10px;font-weight:200;letter-spacing:.5;font-size:1rem;margin-bottom:15px}.picker__box .picker__header .picker__date-display .picker__month-display{text-transform:uppercase;font-size:2rem}.picker__box .picker__header .picker__date-display .picker__day-display{font-size:4.5rem;font-weight:400}.picker__box .picker__header .picker__date-display .picker__year-display{font-size:1.8rem;color:rgba(255,255,255,.4)}.picker__box .picker__header .picker__month,.picker__box .picker__header .picker__year{display:inline-block;margin-left:.25em;margin-right:.25em}.picker__box .picker__header .picker__select--month,.picker__box .picker__header .picker__select--year{height:2em;padding:0;margin-left:.25em;margin-right:.25em;display:inline-block}.picker__box .picker__header .picker__select--month:focus,.picker__box .picker__header .picker__select--year:focus{border-color:rgba(0,0,0,.05)}.picker__box .picker__header .picker__select--year{width:30%}.picker__box .picker__header .picker__select--month.browser-default{display:inline;width:40%}.picker__box .picker__header .picker__select--year.browser-default{display:inline;width:25%}.picker__box .picker__header .picker__nav--next,.picker__box .picker__header .picker__nav--prev{position:absolute;padding:.5em 1.55em;width:1em;height:1em;-webkit-box-sizing:content-box;box-sizing:content-box;bottom:0}.picker__box .picker__header .picker__nav--next:hover,.picker__box .picker__header .picker__nav--prev:hover{cursor:pointer;color:#000;background:#ecf2fc}.picker__box .picker__header .picker__nav--next:before,.picker__box .picker__header .picker__nav--prev:before{content:" ";border-top:.5em solid transparent;border-bottom:.5em solid transparent;border-right:.75em solid #676767;width:0;height:0;display:block;margin:0 auto}.picker__box .picker__header .picker__nav--prev{left:-1em;padding-right:1.25em}.picker__box .picker__header .picker__nav--next{right:-1em;padding-left:1.25em}.picker__box .picker__header .picker__nav--next:before{border-right:0;border-left:.75em solid #676767}.picker__box .picker__header .picker__nav--disabled,.picker__box .picker__header .picker__nav--disabled:before,.picker__box .picker__header .picker__nav--disabled:before:hover,.picker__box .picker__header .picker__nav--disabled:hover{cursor:default;background:0 0;border-right-color:#f5f5f5;border-left-color:#f5f5f5}.picker__box .picker__table{text-align:center;border-collapse:collapse;border-spacing:0;table-layout:fixed;font-size:1rem;width:100%;margin-top:.75em;margin-bottom:.5em}.picker__box .picker__table td,.picker__box .picker__table th{text-align:center}.picker__box .picker__table td{margin:0;padding:0}.picker__box .picker__table .picker__weekday{width:14%;font-size:.9em;padding-bottom:.25em;color:#999;font-weight:500}@media (min-height:33.875em){.picker__box .picker__table .picker__weekday{padding-bottom:.5em}}.picker__box .picker__table .picker__day--today{position:relative;letter-spacing:-.3;padding:.75rem 0;font-weight:400;border:1px solid transparent}.picker__box .picker__table .picker__day.picker__day--today{color:#4285F4}.picker__box .picker__table .picker__day--disabled:before{border-top-color:#aaa}.picker__box .picker__table .picker__day--infocus{color:#595959;letter-spacing:-.3;padding:.75rem 0;font-weight:400;border:1px solid transparent}.picker__box .picker__table .picker__day--infocus:hover{cursor:pointer;color:#000;font-weight:500}.picker__box .picker__table .picker__day--outfocus{display:none;padding:.75rem 0}.picker__box .picker__table .picker__day--outfocus:hover{cursor:pointer;color:#ddd;font-weight:500}.picker__box .picker__table .picker--focused .picker__day--highlighted,.picker__box .picker__table .picker__day--highlighted:hover{cursor:pointer}.picker__box .picker__table .picker--focused,.picker__box .picker__table .picker__day--selected,.picker__box .picker__table .picker__day--selected:hover{border-radius:50%;-webkit-transform:scale(.9);-ms-transform:scale(.9);transform:scale(.9);background-color:#4285F4}.picker__box .picker__table .picker--focused.picker__day--outfocus,.picker__box .picker__table .picker__day--selected.picker__day--outfocus,.picker__box .picker__table .picker__day--selected:hover.picker__day--outfocus{background-color:#ecf2fc}.picker__box .picker__table .picker--focused,.picker__box .picker__table .picker__day--disabled,.picker__box .picker__table .picker__day--disabled:hover{background:#f5f5f5;border-color:#f5f5f5;color:#ddd;cursor:default}.picker__box .picker__table .picker__day--highlighted.picker__day--disabled,.picker__box .picker__table .picker__day--highlighted.picker__day--disabled:hover{background:#bbb}.picker__box .picker__footer{text-align:right;padding:5px 10px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.picker__box .picker__footer .picker__button--clear,.picker__box .picker__footer .picker__button--close,.picker__box .picker__footer .picker__button--today{border:1px solid #fff;background:#fff;font-size:.8em;padding:1rem 0 .7rem;font-weight:700;width:33%;display:inline-block;vertical-align:bottom;text-transform:uppercase}.picker__box .picker__footer .picker__button--clear:hover,.picker__box .picker__footer .picker__button--close:hover,.picker__box .picker__footer .picker__button--today:hover{cursor:pointer;color:#000;background:#b1dcfb;border-bottom-color:#b1dcfb}.picker__box .picker__footer .picker__button--clear:focus,.picker__box .picker__footer .picker__button--close:focus,.picker__box .picker__footer .picker__button--today:focus{background:#b1dcfb;border-color:rgba(0,0,0,.05);outline:0}.picker__box .picker__footer .picker__button--clear:before,.picker__box .picker__footer .picker__button--close:before,.picker__box .picker__footer .picker__button--today:before{position:relative;display:inline-block;height:0}.picker__box .picker__footer .picker__button--clear:before,.picker__box .picker__footer .picker__button--today:before{content:" ";margin-right:.45em}.picker__box .picker__footer .picker__button--today:before{top:-.05em;width:0;border-top:.66em solid #0059bc;border-left:.66em solid transparent}.picker__box .picker__footer .picker__button--clear:before{top:-.25em;width:.66em;border-top:3px solid #e20}.picker__box .picker__footer .picker__button--close:before{content:"\D7";top:-.1em;vertical-align:top;font-size:1.1em;margin-right:.35em;color:#777}.picker__box .picker__footer .picker__button--today[disabled],.picker__box .picker__footer .picker__button--today[disabled]:hover{background:#f5f5f5;border-color:#f5f5f5;color:#ddd;cursor:default}.picker__box .picker__footer .picker__button--today[disabled]:before{border-top-color:#aaa}.picker__calendar-container{padding:0 1rem}.fixed-sn main,.hidden-sn main{padding-top:5.5rem}.picker__calendar-container thead{border:none}.section img{max-width:100%;height:auto}.fixed-sn .double-nav,.fixed-sn footer,.fixed-sn main{padding-left:240px}@media (max-width:1440px){.fixed-sn .double-nav,.fixed-sn footer,.fixed-sn main{padding-left:0}}@media (min-width:600px){.fixed-sn .page-footer .container-fluid,.fixed-sn main{margin-left:2%;margin-right:2%}}@media (min-width:992px){.fixed-sn .page-footer .container-fluid,.fixed-sn main{margin-left:5%;margin-right:5%}}@media (min-width:1200px){.fixed-sn .page-footer .container-fluid,.fixed-sn main{margin-left:6%;margin-right:6%}}.hidden-sn .button-collapse{display:block;position:relative;font-size:1.4rem;margin-right:10px;margin-left:-6px;padding-left:0}.feature-box{text-align:center}.feature-box .feature-title{font-weight:500;margin-bottom:1rem}.feature-box .features-big .feature-title{margin-top:1.5rem;margin-bottom:1.5rem}.feature-box .features-big .fa{font-size:4rem}.feature-box .features-small{text-align:left}.section-blog-fw .author-box,.section-blog-fw .jumbotron,.section-heading{text-align:center}.feature-box .features-small .fa{font-size:2rem}.mdb-feed{margin:1rem 0}.mdb-feed .news{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.mdb-feed .news .label{display:block;-webkit-box-flex:0;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-align-self:stretch;-ms-flex-item-align:stretch;-ms-grid-row-align:stretch;align-self:stretch;width:2.5rem}.mdb-feed .news .label img{width:100%;height:auto}.mdb-feed .news .excerpt{display:block;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-align-self:stretch;-ms-flex-item-align:stretch;-ms-grid-row-align:stretch;align-self:stretch;word-wrap:break-word;margin:0 0 1.2rem 1.2rem}.mdb-feed .news .excerpt .brief{padding-bottom:.5rem;font-weight:500}.mdb-feed .news .excerpt .brief a{color:#4285F4}.mdb-feed .news .excerpt .brief .date,.mdb-feed .news .excerpt .feed-footer .like{font-weight:300;color:#9e9e9e;font-size:.86rem}.mdb-feed .news .excerpt .brief .name{display:inline-block;vertical-align:baseline}.mdb-feed .news .excerpt .brief .date{display:inline-block;float:none;padding-left:.7rem}.mdb-feed .news .excerpt .added-images{margin-bottom:.6rem}.mdb-feed .news .excerpt .added-images img{display:inline-block;margin-right:.3rem;width:7rem}.mdb-feed .news .excerpt .added-text{margin-bottom:.6rem;max-width:450px}.mdb-feed .news .excerpt .feed-footer .like:hover .fa{color:#F44336;-webkit-transition:.4s;transition:.4s}.mdb-feed .news .excerpt .feed-footer .like:hover span{color:#000;-webkit-transition:.4s;transition:.4s}.mdb-feed .news .excerpt .feed-footer .like .fa{padding-right:.5rem}.mdb-feed .news .excerpt .feed-footer span a{padding-right:.3rem;color:#4285F4;cursor:default}.mdb-feed .news .excerpt .feed-footer .thumbs .fa{color:#9e9e9e;-webkit-transition:.4s;transition:.4s}.mdb-feed .news .excerpt .feed-footer .thumbs .fa:hover{color:#757575}.mdb-feed .news .excerpt .feed-footer .thumbs .fa-thumbs-up{padding-right:.3rem}.mdb-feed .news .excerpt .feed-footer .comment{color:#9e9e9e}.card-personal .card-body .card-title{font-weight:400;margin-bottom:.3rem}.card-personal .card-body .card-title.title-one{-webkit-transition:.4s;transition:.4s}.card-personal .card-body .card-title.title-one:hover{color:#4285F4}.card-personal .card-body .card-meta{font-weight:300;font-size:.86rem;color:#757575}.card-personal .card-body .card-meta .fa{padding-right:.5rem}.card-personal .card-body span{-webkit-transition:.5s;transition:.5s}.card-personal .card-body span:hover{color:#4285F4}.news-card .content .right-side-meta{float:right;font-weight:300;color:#9e9e9e;margin-top:.3rem}.news-card .content .avatar-img{width:2rem;margin-right:1rem}.news-card .content img{border-radius:50%;display:inline-block;vertical-align:middle;max-width:100%}.news-card .social-meta .fa{padding-right:.6rem}.news-card .social-meta .fa-heart-o{cursor:pointer;color:rgba(0,0,0,.4);-webkit-transition:.53s;transition:.53s}.news-card .social-meta .fa-heart-o:hover{color:#F44336}.news-card .social-meta span{float:right}.news-card .md-form{margin-top:1.3rem;margin-bottom:.3rem}.news-card .md-form .prefix{font-size:1.5rem;margin-left:.2rem;color:rgba(0,0,0,.4)}.news-card .md-form .prefix .md-form .prefix~textarea,.news-card .md-form .prefix~input{width:-webkit-calc(100% - 4rem);width:calc(100% - 4rem)}.news-card .md-form .prefix.active{color:rgba(0,0,0,.4)}.news-card .md-form .form-control{padding-top:0;padding-bottom:.5rem;margin-left:3rem;margin-bottom:0;height:1.3rem;border-bottom:1px solid rgba(0,0,0,.1)}.no-radius{border-radius:0!important}.section .section-heading{margin-top:2rem;margin-bottom:4rem}.section-heading h1{margin-top:2rem;margin-bottom:3rem}.section-heading p{margin-bottom:3rem;margin-right:15%;margin-left:15%}.section-description{color:#757575;margin-bottom:4rem;margin-left:15%;margin-right:15%;text-align:center}@media (max-width:992px){.section-description{margin-left:5%;margin-right:5%}}.section-blog-fw .view img{border-radius:2px}.section-blog-fw h2{font-weight:300}.section-blog-fw h2 a{color:#424242;-webkit-transition:.2s;transition:.2s}.section-blog-fw h2 a:hover{color:#616161;-webkit-transition:.2s;transition:.2s}.section-blog-fw .excerpt,.section-blog-fw .post-text{margin-left:10%;margin-right:10%;text-align:justify}@media (max-width:992px){.section-blog-fw .excerpt,.section-blog-fw .post-text{margin-left:5%;margin-right:5%}}.section-blog-fw hr{display:block}@media (min-width:1200px){.hr-width{width:83%}}.section.team-section .avatar{margin-bottom:2rem;height:auto}.section.team-section .avatar .rounded-circle{max-width:170px}.section.team-section .avatar img{max-width:200px;height:auto}.section.team-section .title-color{font-weight:400;color:rgba(0,0,0,.6)}.section.team-section h4,.section.team-section h5{margin-bottom:1rem}.section.team-section .grey-text{color:#6e6e6e!important}.section h4{font-weight:400}.section .card-wrapper .fa-repeat,.section .card-wrapper .fa-undo{font-size:15px}.testimonial-carousel .carousel-control{background-image:none;top:50%;-webkit-transform:translateY(-35%);-ms-transform:translateY(-35%);transform:translateY(-35%)}.testimonial-carousel .carousel-control:before{font-size:5rem;color:rgba(0,0,0,.6)}.testimonial-carousel .carousel-control:hover:before{color:#000;-webkit-transition:.4s;transition:.4s}.testimonial-carousel .carousel-control.left{left:6%}.testimonial-carousel .carousel-control.left:before{content:"\2039"}.testimonial-carousel .carousel-control.right{right:6%}.testimonial-carousel .carousel-control.right:before{content:"\203a"}.testimonial-carousel .testimonial{margin-right:15%;margin-left:15%}.testimonial-carousel .testimonial .avatar{margin-bottom:2rem}.testimonial-carousel .testimonial .avatar img{max-width:170px}.testimonial-carousel .testimonial h4{margin-bottom:1.3rem;font-weight:500}.testimonial-carousel .testimonial h5{margin-bottom:.9rem;color:#424242;font-weight:400}.testimonial-carousel .testimonial p{color:#666}.card-body h3,.card-body h5{font-weight:400;margin-bottom:1rem}.card-body h4{font-weight:500;margin-bottom:1rem}.card-body a h5{font-size:1rem}.magazine-section .view{margin-bottom:2rem}.magazine-section .single-news{border-bottom:1px solid #e0e0e0;margin-bottom:1.5rem}.magazine-section .single-news:last-of-type{border-bottom:none}@media (max-width:772px){.magazine-section .single-news{padding-bottom:1rem}}.magazine-section .single-news .news-data{margin-bottom:5rem}.magazine-section .single-news .news-data h6{float:left}.magazine-section .single-news .news-data p,.magazine-section .single-news a .fa-angle-right{float:right}.magazine-section .single-news h3{margin-top:1.5rem;margin-bottom:1.5rem}.magazine-section .single-news a{color:#424242;font-weight:300;margin-bottom:1rem}.magazine-section .single-news a:hover{color:#616161;-webkit-transition:.2s;transition:.2s}.magazine-section .single-news p{color:#757575}.magazine-section .single-news strong{font-weight:500}.magazine-section.multi-columns h6{margin-bottom:1.5rem;text-align:center}.magazine-section.multi-columns .view{margin-bottom:2rem}.magazine-section.multi-columns .single-news{padding-bottom:1rem}.magazine-section.multi-columns .single-news strong{font-size:1.2rem}.pricing-card{text-align:center}.pricing-card p{font-size:1rem}.pricing-card ul{list-style-type:none;padding:0}.pricing-card .header{border-radius:6px 6px 0 0;color:#fff}.pricing-card .header h4{padding:2.5rem;font-weight:500}.pricing-card .price{position:relative;padding-top:3rem}.pricing-card .price h1,.pricing-card .price h2{font-size:5rem;padding:1.5rem;font-weight:300}.pricing-card .price h1:before,.pricing-card .price h2:before{content:"$";font-size:30px;position:absolute;margin-left:-1.2rem;margin-top:.7rem}.pricing-card .price h1:after,.pricing-card .price h2:after{content:"/mo";font-size:30px;position:absolute;margin-top:3rem}.pricing-card .price .version{position:absolute;top:0;width:100%;background-color:rgba(0,0,0,.3);padding:1rem}.pricing-card .price .version h5{padding:0;margin:0}.pricing-card .heading h1{font-size:4rem;font-weight:400}.pricing-card .striped{padding:.6rem}.naked-card .price,.pricing-card.card-overlay .price{padding-top:0}.pricing-card .striped .fa{margin-right:5px}.pricing-card .striped .fa-check{color:green}.pricing-card .striped .fa-times{color:red}.pricing-card .striped li{border-bottom:1px solid rgba(153,153,153,.298039);margin-bottom:1rem}.pricing-card.card-overlay{display:block;color:#fff}.pricing-card.card-overlay p{color:#fff}.pricing-card .green-striped li{border-color:#33c28a}.pricing-card .orange-striped li{border-color:#e97d63}.pricing-card .purple-striped li{border-color:#963c94}.pricing-card .card-background{background-color:#28283f;border-radius:0 0 6px 6px}.card .card-circle{border:2px solid #e0e0e0;height:120px;width:120px;margin-bottom:2rem;border-radius:50%}.card .card-circle .fa{font-size:4rem}.naked-card h5{margin-top:1.2rem}.form-header{color:#fff;text-align:center;margin-top:-50px;margin-bottom:3rem;padding:1rem;border-radius:2px}.card .card-body h3{margin-bottom:0;padding:.7rem}.md-form .prefix.grey-text{font-size:1.5rem;margin-top:1rem}.section .contact-icons{text-align:center;list-style-type:none;padding:0}.section .contact-icons li{margin-bottom:2.2rem}section .form form .btn-floating{float:right;position:relative;bottom:3rem;margin-right:0}section .contact{background-color:#103f6d;height:100%}section .contact .contact-icons li i{float:left;clear:both;margin-right:1rem}section .contact .contact-icons li i.fa{font-size:1.5rem}section .contact .contact-icons li p{padding-top:.5rem;text-align:left}section .contact i{color:#6b89a5}code[class*=language-],pre[class*=language-]{color:#292b2c;background:#eaeaea;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;font-size:.85rem;-moz-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}:not(pre)>code[class*=language-],pre[class*=language-]{background:#eaeaea}pre[class*=language-]{-webkit-box-shadow:0 1px 6px 0 rgba(0,0,0,.2),0 1px 6px 0 rgba(0,0,0,.19);box-shadow:0 1px 6px 0 rgba(0,0,0,.2),0 1px 6px 0 rgba(0,0,0,.19);margin:2.5em 0;overflow:auto;padding:1em}pre[class*=language-]::-moz-selection{background:rgba(3,169,244,.7)}code[class*=language-]::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:rgba(3,169,244,.7)}code[class*=language-]::selection,pre[class*=language-]::selection{text-shadow:none;background:rgba(3,169,244,.7)}pre[class*=language-] span::-moz-selection{background:rgba(3,169,244,.7)}code[class*=language-] span::-moz-selection,pre[class*=language-] span::-moz-selection{text-shadow:none;background:rgba(3,169,244,.7)}code[class*=language-] span::selection,pre[class*=language-] span::selection{text-shadow:none;background:rgba(3,169,244,.7)}:not(pre)>code[class*=language-]{border:.13em solid #545454;-webkit-box-shadow:1px 1px .3em -.1em #000 inset;box-shadow:1px 1px .3em -.1em #000 inset;padding:.15em .2em .05em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#777}.namespace,.token.punctuation{opacity:.7}.token.boolean,.token.deleted,.token.number,.token.tag{color:#ce6849}.token.tag{-webkit-box-shadow:none;box-shadow:none;text-shadow:none;font-weight:400;display:inline;padding:0}.token.builtin,.token.constant,.token.keyword,.token.property,.token.selector,.token.symbol{color:#328946}.language-css .token.string,.style .token.string,.token.attr-name,.token.attr-value,.token.char,.token.entity,.token.inserted,.token.operator,.token.string,.token.url,.token.variable{color:#b4284f}.token.atrule{color:#7385a5}.token.important,.token.regex{color:#e8c062}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}pre[data-line]{padding:1em 0 1em 3em;position:relative}.language-markup .token.attr-name,.language-markup .token.punctuation,.language-markup .token.tag{color:#2456a0}.token{position:relative;z-index:1}.line-highlight{background:-webkit-linear-gradient(to right,rgba(84,84,84,.1) 70%,rgba(84,84,84,0));background:rgba(84,84,84,.25);background:-webkit-gradient(linear,left top,right top,color-stop(70%,rgba(84,84,84,.1)),color-stop(70%,rgba(84,84,84,0)));background:-webkit-linear-gradient(left,rgba(84,84,84,.1) 70%,rgba(84,84,84,0));background:linear-gradient(to right,rgba(84,84,84,.1) 70%,rgba(84,84,84,0));border-bottom:1px dashed #545454;border-top:1px dashed #545454;left:0;line-height:inherit;margin-top:.75em;padding:inherit 0;pointer-events:none;position:absolute;right:0;white-space:pre;z-index:0}.line-highlight:before,.line-highlight[data-end]:after{background-color:#8693a6;border-radius:999px;-webkit-box-shadow:0 1px #fff;box-shadow:0 1px #fff;color:#f4f1ef;content:attr(data-start);font:700 65%/1.5 sans-serif;left:.6em;min-width:1em;padding:0 .5em;position:absolute;text-align:center;text-shadow:none;top:.4em;vertical-align:.3em}.line-highlight[data-end]:after{bottom:.4em;content:attr(data-end);top:auto}pre.code-toolbar{position:relative}pre.code-toolbar>.toolbar{position:absolute;top:.3em;right:.3em;background:#f5f2f0;background:rgba(224,224,224,.2)}pre.code-toolbar>.toolbar a{color:#6e6e6e;font-size:.9rem;cursor:pointer;padding:0 .5em;font-weight:600}pre.code-toolbar>.toolbar a.zeroclipboard-is-hover,pre.code-toolbar>.toolbar a:focus,pre.code-toolbar>.toolbar a:hover{color:inherit}.wpcf7-submit,div.bbp-submit-wrapper button{line-height:1.33333;position:relative;padding:5px 22px;border:0;margin:10px;cursor:pointer;border-radius:2px;text-transform:uppercase;text-decoration:none;outline:0!important;color:#fff!important;-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);-webkit-transition:.2s ease-out;transition:.2s ease-out;background-color:#154771!important}.wpcf7-submit:hover,div.bbp-submit-wrapper button:hover{-webkit-box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);background-color:#1d629c!important}.wpcf7-submit:focus,div.bbp-submit-wrapper button:focus{background-color:#1d629c!important}@media only screen and (min-width:992px){footer.page-footer .col-md-4{margin-left:2rem}}.price-select{margin-left:30%;margin-right:30%}@media only screen and (max-width:992px){.price-select{margin-left:25%;margin-right:25%}}@media only screen and (max-width:768px){.price-select{margin-left:15%;margin-right:15%}}@media only screen and (max-width:500px){.price-select{margin-left:5%;margin-right:5%}}.side-nav .collapsible a{height:40px;line-height:40px;margin-bottom:0}.side-nav .collapsible .collapsible-body a{height:32px;line-height:32px}.side-nav .fa-angle-down.rotate-icon{top:12px}.side-nav #mdw_main_search{height:1.1rem}.side-nav .form-group{margin-bottom:.7rem}.side-nav .current-menu-item a{background:#33b5e5}#menu-item-403,#menu-item-43627,#menu-item-43629,#menu-item-44795{border-top:1px solid rgba(153,153,153,.298039)}#bbpress-forums div.bbp-the-content-wrapper textarea.bbp-the-content{height:200px}#bbpress-forums #bbp-search-form{margin-bottom:2rem}#bbp_search_submit{border-radius:0;border:0;-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);-webkit-transition:.2s ease-out;transition:.2s ease-out;color:#fff;margin:6px;background-color:#154771!important;padding:.6rem 1.05rem;font-size:1.05rem;line-height:1.11}#bbp_search_submit:hover{-webkit-box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);color:#fff}#bbp_search_submit.active,#bbp_search_submit:active,#bbp_search_submit:focus{outline:0;color:#fff}#bbp_search_submit:focus,#bbp_search_submit:hover{background-color:#1d629c!important}.newsfeed .img-fluid{width:100%}.documentation .doc-title{border-top:1px solid #e0e0e0;border-bottom:1px solid #e0e0e0;padding:2rem 0;margin:5rem 0 2rem;text-transform:uppercase;font-size:2rem}.documentation .doc-title.doc-first{border-top:none;margin-top:0;padding-top:1.2rem}.documentation .doc-title.doc-subtitle{text-transform:none;border-top:none;font-size:1.7rem;margin-top:2rem}.documentation .doc-title .btn{margin-top:-2px}@media (max-width:776px){.documentation .doc-title .btn{margin-top:1rem;display:block}}.documentation .col-example{padding:1rem;background-color:#33b5e5;border:2px solid #fff;color:#fff;text-align:center}.documentation .example-td{padding:1rem;background-color:#33b5e5!important;border:2px solid #fff!important;color:#fff}.documentation .example-parent{background-color:#eee!important}.documentation li.circle-li{list-style-type:disc}.documentation ul.ul-flex{padding-left:3rem}.documentation .is-visible{background-color:#bbdefb}.documentation .is-hidden{color:#9e9e9e}.documentation .scroll-box{position:relative}.documentation .scrollspy-example{overflow-y:scroll;position:relative;height:200px;padding:1rem}.documentation .dzik:after{content:"Wrrr. jestem wielkim strasznym dzikiem"}.documentation footer{padding-left:0}.color-block,.color-block-dark{height:130px;padding:40px;text-align:center;color:#fff}.color-block-dark h5{font-size:1rem}.dynamic-color .col-md-4{margin-bottom:2rem}.dynamic-color .col-md-4 div{padding:7px 20px}#comments .comment-text{margin-top:1rem}#comments button,#comments html input[type=button],#comments input[type=reset],#comments input[type=submit]{display:inline-block;padding:.375rem 1rem;font-size:1rem;font-weight:400;line-height:1.5;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-radius:0;border:0;-webkit-box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);-webkit-transition:.2s ease-out;transition:.2s ease-out;color:#fff;margin:6px}.bbp-author-ip,.variations_form label:not(.active) .fa.fa-check{display:none}.author-box,.comments-section{margin-bottom:2rem}#comments button:hover,#comments html input[type=button]:hover,#comments input[type=reset]:hover,#comments input[type=submit]:hover{-webkit-box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);color:#fff}p.form-submit i.btn input[type=submit],p.form-submit i.btn input[type=submit]:hover{-webkit-box-shadow:none!important;box-shadow:none!important}.comments-section{padding-top:1rem}#billing_vat_field,.main-title{margin-bottom:1.5rem}.comments-section .avatar{max-width:100px!important}.tutorial-content pre.code-toolbar{max-height:450px!important}.tutorial-content p{text-align:justify}input[name=quantity]{position:absolute;left:-99999px}.product_meta{position:absolute;top:-1000px}.variable_name label{font-size:1.3rem}.single_variation span,p.price{font-size:2.5rem}code[class*=language-],pre[class*=language-]{max-height:450px}.mdb-skin-custom .navbar{color:#fff}.mdb-skin-custom .navbar .navbar-nav .nav-item .dropdown-menu a:active,.mdb-skin-custom .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.mdb-skin-custom .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#1dade2}.mdb-skin-custom .page-footer{background-color:#243a51}.mdb-skin-custom .side-nav{background-color:#224562}.mdb-skin-custom .side-nav .social a:hover .fa{color:#33b5e5!important;-webkit-transition:all .3s linear;transition:all .3s linear}.mdb-skin-custom .side-nav .collapsible li{background-color:transparent}.mdb-skin-custom .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.mdb-skin-custom .side-nav .collapsible li .collapsible-header.active,.mdb-skin-custom .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(72,198,255,.8)}.mdb-skin-custom .side-nav .collapsible li .collapsible-body a{color:#fff}.mdb-skin-custom .side-nav .collapsible li .collapsible-body a:hover{background-color:transparent;color:#67d5ff}.mdb-skin-custom .side-nav .fa{color:#fff}.mdb-skin-custom .side-nav .sidenav-bg.mask-strong:after,.mdb-skin-custom .side-nav .sidenav-bg:after{background:rgba(13,36,60,.85)}.mdb-skin-custom .side-nav .sidenav-bg.mask-light:after{background:rgba(13,36,60,.65)}.mdb-skin-custom .side-nav .sidenav-bg.mask-slight:after{background:rgba(13,36,60,.5)}.mdb-skin-custom .side-nav .sidenav-bg:after{z-index:-1}.mdb-skin-custom .btn-ptc{background:#08aae6}.mdb-skin-custom .btn-ptc:focus,.mdb-skin-custom .btn-ptc:hover{background-color:#4abde8!important}.mdb-skin-custom .btn-ptc.active{background-color:#14799e!important}.mdb-skin-custom .btn-dtc{background:#086fb9}.mdb-skin-custom .btn-dtc:focus,.mdb-skin-custom .btn-dtc:hover{background-color:#1e71ae!important}.mdb-skin-custom .btn-dtc.active{background-color:#0b2a41!important}.mdb-skin-custom .btn-stc{background:#083761}.mdb-skin-custom .btn-stc:focus,.mdb-skin-custom .btn-stc:hover{background-color:#114a7d!important}.mdb-skin-custom .btn-stc.active{background-color:#02080d!important}.mdb-skin-custom .form-header-custom{background:#1b95c1!important}.angular-skin .navbar{background-color:#4c576c;color:#fff}.angular-skin .navbar .navbar-nav .nav-item .dropdown-menu a:active,.angular-skin .navbar .navbar-nav .nav-item .dropdown-menu a:focus,.angular-skin .navbar .navbar-nav .nav-item .dropdown-menu a:hover{background-color:#1dade2}.angular-skin .page-footer{background-color:#4c576c}.angular-skin .side-nav{background-color:#224562}.angular-skin .side-nav .social a:hover .fa{color:#33b5e5!important;-webkit-transition:all .3s linear;transition:all .3s linear}.angular-skin .side-nav .collapsible li{background-color:transparent}.angular-skin .side-nav .collapsible li .collapsible-header{color:#fff;-webkit-transition:all .3s linear;transition:all .3s linear}.angular-skin .side-nav .collapsible li .collapsible-header.active,.angular-skin .side-nav .collapsible li .collapsible-header:hover{background-color:rgba(232,44,64,.8)}.angular-skin .side-nav .collapsible li .collapsible-body a{color:#fff}.angular-skin .side-nav .collapsible li .collapsible-body a:hover{background-color:transparent;color:#fc96ad}.angular-skin .side-nav .fa{color:#fff}.angular-skin .side-nav .sidenav-bg.mask-strong:after,.angular-skin .side-nav .sidenav-bg:after{background:rgba(52,64,86,.85)}.angular-skin .side-nav .sidenav-bg.mask-light:after{background:rgba(52,64,86,.65)}.angular-skin .side-nav .sidenav-bg.mask-slight:after{background:rgba(52,64,86,.5)}.angular-skin .btn-ptc{background:#08aae6}.angular-skin .btn-ptc:focus,.angular-skin .btn-ptc:hover{background-color:#4abde8!important}.angular-skin .btn-ptc.active{background-color:#14799e!important}.angular-skin .btn-dtc{background:#086fb9}.angular-skin .btn-dtc:focus,.angular-skin .btn-dtc:hover{background-color:#1e71ae!important}.angular-skin .btn-dtc.active{background-color:#0b2a41!important}.angular-skin .btn-stc{background:#083761}.angular-skin .btn-stc:focus,.angular-skin .btn-stc:hover{background-color:#114a7d!important}.angular-skin .btn-stc.active{background-color:#02080d!important}.angular-skin .form-header-custom{background:#1b95c1!important}#billing_vat_field label{font-size:1.2rem;font-weight:500}div.dropdown-wrapper{position:relative;width:100%;height:0}ul.search-dropdown{position:absolute;top:-20px;width:100%;background-color:#293a48;padding:20px 0;z-index:100}ul.search-dropdown li{padding:0 5px}ul.search-dropdown li a{color:#fff;line-height:30px;height:30px}ul.search-dropdown li a:hover{background:rgba(0,0,0,.12)}.variations_form label{width:100%;font-size:.7rem;padding:.85rem 1.5rem}.variations_form .btn-group .btn+.btn{margin-left:0!important}@media (min-width:992px){.variations_form label{width:50%}}@media (min-width:1200px){.variations_form label{width:auto}}.variations_form label.active .fa{margin-left:7px;font-size:.9rem;color:#fff}.woocommerce-MyAccount-navigation ul{padding:.7rem;margin-left:1rem;margin-right:1rem;position:relative}.woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link{display:inline-block}.woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link a{-webkit-border-radius:2px;-moz-border-radius:2px;-ms-border-radius:2px;-o-border-radius:2px;color:#666;text-align:center;padding:10px}.woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link:not(.is-active) a:hover{background:rgba(158,158,158,.3)}.woocommerce-MyAccount-navigation ul li.woocommerce-MyAccount-navigation-link.is-active a{background:#3F729B;color:#fff;-webkit-box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15)}.error404{min-height:100vh;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.error404 main{-webkit-box-flex:2;-webkit-flex:2 0 auto;-ms-flex:2 0 auto;flex:2 0 auto}#wpadminbar{top:auto;bottom:0}@media screen and (max-width:600px){#wpadminbar{position:fixed}}#wpadminbar .menupop .ab-sub-wrapper,#wpadminbar .shortlink-input{bottom:32px}@media screen and (max-width:782px){#wpadminbar .menupop .ab-sub-wrapper,#wpadminbar .shortlink-input{bottom:46px}}@media screen and (min-width:783px){.admin-bar.masthead-fixed .site-header{top:0}}img[alt=amex]{display:none!important}.header-breadcrumb .breadcrumb-item.active{color:rgba(255,255,255,.65)}.reviews-rating{display:inline-block;width:184px;height:28px;background-image:url(https://mdbootstrap.com/img/Others/stars.png);background-repeat:no-repeat}.stars-5{background-position:-15px -22px}.stars-4{background-position:-15px -76px}.stars-3{background-position:-15px -134px}.stars-2{background-position:-15px -190px}.stars-1{background-position:-15px -248px}@media (max-width:760px){.modal-backdrop,.side-modal{display:none!important}}.main-title:before,.title:before{display:block;height:6rem;margin-top:-6rem;visibility:hidden;content:""}#scrollspy{width:100%}#scrollspy a{font-size:.9rem}.scrollspy-col{margin-left:6%}.main-title{font-size:3.5rem}.title{margin-bottom:1rem}.fa,.fa-stack{display:inline-block}.description{margin-bottom:2rem}.related-content-heading{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;overflow:visible;padding-top:.5rem;padding-bottom:.3125rem;margin-right:1rem;line-height:inherit;white-space:nowrap}.mdb-sidenav,.sr-only{overflow:hidden}.fa.fa-pull-left,.fa.pull-left{margin-right:.3em}.side-nav .logo-sn{padding-bottom:1rem;padding-top:1rem}.side-nav .search-form{margin-top:0;border-top:1px solid rgba(255,255,255,.65)}.side-nav .search-form input[type=text]{border-bottom:1px solid rgba(255,255,255,.65)}.navbar .notifications-nav .dropdown-menu{width:23rem}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.dwqa-search,.dwqa-user-block{margin-bottom:3rem}.dwqa-search{margin-right:1.8rem}.dwqa-sort-by{margin-top:-20px}.wp-editor-area{height:300px}.btn-submit-dwqa,.dwqa-btn-primary{font-size:1rem;padding:.2rem 1rem;margin-bottom:3rem}.dwqa-leaderboard img{border-radius:50%;-webkit-box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);box-shadow:0 5px 11px 0 rgba(0,0,0,.18),0 4px 15px 0 rgba(0,0,0,.15);float:left;margin-right:20px}.dwqa-user-header{font-size:1.1rem}.dwqa-container .rounded,.dwqa-container label{font-weight:500;font-size:1.25rem;text-align:center}.dwqa-container .rounded{margin-bottom:2rem} \ No newline at end of file diff --git a/Documents/css/swiper.min.css b/Documents/css/swiper.min.css new file mode 100644 index 000000000..b222bea4d --- /dev/null +++ b/Documents/css/swiper.min.css @@ -0,0 +1,15 @@ +/** + * Swiper 3.4.2 + * Most modern mobile touch slider and framework with hardware accelerated transitions + * + * http://www.idangero.us/swiper/ + * + * Copyright 2017, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: March 10, 2017 + */ +.swiper-container{margin-left:auto;margin-right:auto;position:relative;overflow:hidden;z-index:1}.swiper-container-no-flexbox .swiper-slide{float:left}.swiper-container-vertical>.swiper-wrapper{-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.swiper-wrapper{position:relative;width:100%;height:100%;z-index:1;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate(0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.swiper-container-multirow>.swiper-wrapper{-webkit-box-lines:multiple;-moz-box-lines:multiple;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;width:100%;height:100%;position:relative}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start;-webkit-transition-property:-webkit-transform,height;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform,height}.swiper-container .swiper-notification{position:absolute;left:0;top:0;pointer-events:none;opacity:0;z-index:-1000}.swiper-wp8-horizontal{-ms-touch-action:pan-y;touch-action:pan-y}.swiper-wp8-vertical{-ms-touch-action:pan-x;touch-action:pan-x}.swiper-button-next,.swiper-button-prev{position:absolute;top:50%;width:27px;height:44px;margin-top:-22px;z-index:10;cursor:pointer;-moz-background-size:27px 44px;-webkit-background-size:27px 44px;background-size:27px 44px;background-position:center;background-repeat:no-repeat}.swiper-button-next.swiper-button-disabled,.swiper-button-prev.swiper-button-disabled{opacity:.35;cursor:auto;pointer-events:none}.swiper-button-prev,.swiper-container-rtl .swiper-button-next{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");left:10px;right:auto}.swiper-button-prev.swiper-button-black,.swiper-container-rtl .swiper-button-next.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-prev.swiper-button-white,.swiper-container-rtl .swiper-button-next.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next,.swiper-container-rtl .swiper-button-prev{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");right:10px;left:auto}.swiper-button-next.swiper-button-black,.swiper-container-rtl .swiper-button-prev.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next.swiper-button-white,.swiper-container-rtl .swiper-button-prev.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-pagination{position:absolute;text-align:center;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;transition:.3s;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-container-horizontal>.swiper-pagination-bullets,.swiper-pagination-custom,.swiper-pagination-fraction{bottom:10px;left:0;width:100%}.swiper-pagination-bullet{width:8px;height:8px;display:inline-block;border-radius:100%;background:#000;opacity:.2}button.swiper-pagination-bullet{border:none;margin:0;padding:0;box-shadow:none;-moz-appearance:none;-ms-appearance:none;-webkit-appearance:none;appearance:none}.swiper-pagination-clickable .swiper-pagination-bullet{cursor:pointer}.swiper-pagination-white .swiper-pagination-bullet{background:#fff}.swiper-pagination-bullet-active{opacity:1;background:#007aff}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination-bullets{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);-moz-transform:translate3d(0,-50%,0);-o-transform:translate(0,-50%);-ms-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination-bullets .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet{margin:0 5px}.swiper-pagination-progress{background:rgba(0,0,0,.25);position:absolute}.swiper-pagination-progress .swiper-pagination-progressbar{background:#007aff;position:absolute;left:0;top:0;width:100%;height:100%;-webkit-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left top}.swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar{-webkit-transform-origin:right top;-moz-transform-origin:right top;-ms-transform-origin:right top;-o-transform-origin:right top;transform-origin:right top}.swiper-container-horizontal>.swiper-pagination-progress{width:100%;height:4px;left:0;top:0}.swiper-container-vertical>.swiper-pagination-progress{width:4px;height:100%;left:0;top:0}.swiper-pagination-progress.swiper-pagination-white{background:rgba(255,255,255,.5)}.swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar{background:#fff}.swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar{background:#000}.swiper-container-3d{-webkit-perspective:1200px;-moz-perspective:1200px;-o-perspective:1200px;perspective:1200px}.swiper-container-3d .swiper-cube-shadow,.swiper-container-3d .swiper-slide,.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top,.swiper-container-3d .swiper-wrapper{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d}.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-container-3d .swiper-slide-shadow-left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to left,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-right{background-image:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to right,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-top{background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to top,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-bottom{background-image:-webkit-gradient(linear,left bottom,left top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-coverflow .swiper-wrapper,.swiper-container-flip .swiper-wrapper{-ms-perspective:1200px}.swiper-container-cube,.swiper-container-flip{overflow:visible}.swiper-container-cube .swiper-slide,.swiper-container-flip .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;z-index:1}.swiper-container-cube .swiper-slide .swiper-slide,.swiper-container-flip .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-active .swiper-slide-active,.swiper-container-flip .swiper-slide-active,.swiper-container-flip .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-cube .swiper-slide-shadow-bottom,.swiper-container-cube .swiper-slide-shadow-left,.swiper-container-cube .swiper-slide-shadow-right,.swiper-container-cube .swiper-slide-shadow-top,.swiper-container-flip .swiper-slide-shadow-bottom,.swiper-container-flip .swiper-slide-shadow-left,.swiper-container-flip .swiper-slide-shadow-right,.swiper-container-flip .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-slide{visibility:hidden;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;width:100%;height:100%}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-transform-origin:100% 0;-moz-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-next,.swiper-container-cube .swiper-slide-next+.swiper-slide,.swiper-container-cube .swiper-slide-prev{pointer-events:auto;visibility:visible}.swiper-container-cube .swiper-cube-shadow{position:absolute;left:0;bottom:0;width:100%;height:100%;background:#000;opacity:.6;-webkit-filter:blur(50px);filter:blur(50px);z-index:0}.swiper-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide{pointer-events:none;-webkit-transition-property:opacity;-moz-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.swiper-container-fade .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide-active,.swiper-container-fade .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-zoom-container{width:100%;height:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-moz-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-moz-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;text-align:center}.swiper-zoom-container>canvas,.swiper-zoom-container>img,.swiper-zoom-container>svg{max-width:100%;max-height:100%;object-fit:contain}.swiper-scrollbar{border-radius:10px;position:relative;-ms-touch-action:none;background:rgba(0,0,0,.1)}.swiper-container-horizontal>.swiper-scrollbar{position:absolute;left:1%;bottom:3px;z-index:50;height:5px;width:98%}.swiper-container-vertical>.swiper-scrollbar{position:absolute;right:3px;top:1%;z-index:50;width:5px;height:98%}.swiper-scrollbar-drag{height:100%;width:100%;position:relative;background:rgba(0,0,0,.5);border-radius:10px;left:0;top:0}.swiper-scrollbar-cursor-drag{cursor:move}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;-webkit-transform-origin:50%;-moz-transform-origin:50%;transform-origin:50%;-webkit-animation:swiper-preloader-spin 1s steps(12,end) infinite;-moz-animation:swiper-preloader-spin 1s steps(12,end) infinite;animation:swiper-preloader-spin 1s steps(12,end) infinite}.swiper-lazy-preloader:after{display:block;content:"";width:100%;height:100%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");background-position:50%;-webkit-background-size:100%;background-size:100%;background-repeat:no-repeat}.swiper-lazy-preloader-white:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}@-webkit-keyframes swiper-preloader-spin{100%{-webkit-transform:rotate(360deg)}}@keyframes swiper-preloader-spin{100%{transform:rotate(360deg)}} \ No newline at end of file diff --git a/Documents/instructions/Nest Developer - Nest Product.docx b/Documents/instructions/Nest Developer - Nest Product.docx index 74dddcbc5..f738f466e 100644 Binary files a/Documents/instructions/Nest Developer - Nest Product.docx and b/Documents/instructions/Nest Developer - Nest Product.docx differ diff --git a/Documents/instructions/Nest Developer - Nest Product.pdf b/Documents/instructions/Nest Developer - Nest Product.pdf index 4e3286ee7..43678b287 100644 Binary files a/Documents/instructions/Nest Developer - Nest Product.pdf and b/Documents/instructions/Nest Developer - Nest Product.pdf differ diff --git a/Documents/js/bootstrap.min.js b/Documents/js/bootstrap.min.js new file mode 100644 index 000000000..27aace313 --- /dev/null +++ b/Documents/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.0.0-beta.2 (https://getbootstrap.com) + * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +var bootstrap=function(t,e,n){"use strict";function i(t,e){for(var n=0;n0?n:null}catch(t){return null}},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){e(t).trigger(r.end)},supportsTransitionEnd:function(){return Boolean(r)},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(e,n,i){for(var s in i)if(Object.prototype.hasOwnProperty.call(i,s)){var r=i[s],o=n[s],l=o&&a.isElement(o)?"element":t(o);if(!new RegExp(r).test(l))throw new Error(e.toUpperCase()+': Option "'+s+'" provided type "'+l+'" but expected type "'+r+'".')}}};return r=i(),e.fn.emulateTransitionEnd=s,a.supportsTransitionEnd()&&(e.event.special[a.TRANSITION_END]=n()),a}(),r=function(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t},o=function(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e},a=function(){var t="alert",n=e.fn[t],i={CLOSE:"close.bs.alert",CLOSED:"closed.bs.alert",CLICK_DATA_API:"click.bs.alert.data-api"},o={ALERT:"alert",FADE:"fade",SHOW:"show"},a=function(){function t(t){this._element=t}var n=t.prototype;return n.close=function(t){t=t||this._element;var e=this._getRootElement(t);this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},n.dispose=function(){e.removeData(this._element,"bs.alert"),this._element=null},n._getRootElement=function(t){var n=s.getSelectorFromElement(t),i=!1;return n&&(i=e(n)[0]),i||(i=e(t).closest("."+o.ALERT)[0]),i},n._triggerCloseEvent=function(t){var n=e.Event(i.CLOSE);return e(t).trigger(n),n},n._removeElement=function(t){var n=this;e(t).removeClass(o.SHOW),s.supportsTransitionEnd()&&e(t).hasClass(o.FADE)?e(t).one(s.TRANSITION_END,function(e){return n._destroyElement(t,e)}).emulateTransitionEnd(150):this._destroyElement(t)},n._destroyElement=function(t){e(t).detach().trigger(i.CLOSED).remove()},t._jQueryInterface=function(n){return this.each(function(){var i=e(this),s=i.data("bs.alert");s||(s=new t(this),i.data("bs.alert",s)),"close"===n&&s[n](this)})},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},r(t,null,[{key:"VERSION",get:function(){return"4.0.0-beta.2"}}]),t}();return e(document).on(i.CLICK_DATA_API,{DISMISS:'[data-dismiss="alert"]'}.DISMISS,a._handleDismiss(new a)),e.fn[t]=a._jQueryInterface,e.fn[t].Constructor=a,e.fn[t].noConflict=function(){return e.fn[t]=n,a._jQueryInterface},a}(),l=function(){var t="button",n=e.fn[t],i={ACTIVE:"active",BUTTON:"btn",FOCUS:"focus"},s={DATA_TOGGLE_CARROT:'[data-toggle^="button"]',DATA_TOGGLE:'[data-toggle="buttons"]',INPUT:"input",ACTIVE:".active",BUTTON:".btn"},o={CLICK_DATA_API:"click.bs.button.data-api",FOCUS_BLUR_DATA_API:"focus.bs.button.data-api blur.bs.button.data-api"},a=function(){function t(t){this._element=t}var n=t.prototype;return n.toggle=function(){var t=!0,n=!0,r=e(this._element).closest(s.DATA_TOGGLE)[0];if(r){var o=e(this._element).find(s.INPUT)[0];if(o){if("radio"===o.type)if(o.checked&&e(this._element).hasClass(i.ACTIVE))t=!1;else{var a=e(r).find(s.ACTIVE)[0];a&&e(a).removeClass(i.ACTIVE)}if(t){if(o.hasAttribute("disabled")||r.hasAttribute("disabled")||o.classList.contains("disabled")||r.classList.contains("disabled"))return;o.checked=!e(this._element).hasClass(i.ACTIVE),e(o).trigger("change")}o.focus(),n=!1}}n&&this._element.setAttribute("aria-pressed",!e(this._element).hasClass(i.ACTIVE)),t&&e(this._element).toggleClass(i.ACTIVE)},n.dispose=function(){e.removeData(this._element,"bs.button"),this._element=null},t._jQueryInterface=function(n){return this.each(function(){var i=e(this).data("bs.button");i||(i=new t(this),e(this).data("bs.button",i)),"toggle"===n&&i[n]()})},r(t,null,[{key:"VERSION",get:function(){return"4.0.0-beta.2"}}]),t}();return e(document).on(o.CLICK_DATA_API,s.DATA_TOGGLE_CARROT,function(t){t.preventDefault();var n=t.target;e(n).hasClass(i.BUTTON)||(n=e(n).closest(s.BUTTON)),a._jQueryInterface.call(e(n),"toggle")}).on(o.FOCUS_BLUR_DATA_API,s.DATA_TOGGLE_CARROT,function(t){var n=e(t.target).closest(s.BUTTON)[0];e(n).toggleClass(i.FOCUS,/^focus(in)?$/.test(t.type))}),e.fn[t]=a._jQueryInterface,e.fn[t].Constructor=a,e.fn[t].noConflict=function(){return e.fn[t]=n,a._jQueryInterface},a}(),h=function(){var t="carousel",n="bs.carousel",i="."+n,o=e.fn[t],a={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0},l={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean"},h={NEXT:"next",PREV:"prev",LEFT:"left",RIGHT:"right"},c={SLIDE:"slide"+i,SLID:"slid"+i,KEYDOWN:"keydown"+i,MOUSEENTER:"mouseenter"+i,MOUSELEAVE:"mouseleave"+i,TOUCHEND:"touchend"+i,LOAD_DATA_API:"load.bs.carousel.data-api",CLICK_DATA_API:"click.bs.carousel.data-api"},u={CAROUSEL:"carousel",ACTIVE:"active",SLIDE:"slide",RIGHT:"carousel-item-right",LEFT:"carousel-item-left",NEXT:"carousel-item-next",PREV:"carousel-item-prev",ITEM:"carousel-item"},d={ACTIVE:".active",ACTIVE_ITEM:".active.carousel-item",ITEM:".carousel-item",NEXT_PREV:".carousel-item-next, .carousel-item-prev",INDICATORS:".carousel-indicators",DATA_SLIDE:"[data-slide], [data-slide-to]",DATA_RIDE:'[data-ride="carousel"]'},f=function(){function o(t,n){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this._config=this._getConfig(n),this._element=e(t)[0],this._indicatorsElement=e(this._element).find(d.INDICATORS)[0],this._addEventListeners()}var f=o.prototype;return f.next=function(){this._isSliding||this._slide(h.NEXT)},f.nextWhenVisible=function(){!document.hidden&&e(this._element).is(":visible")&&"hidden"!==e(this._element).css("visibility")&&this.next()},f.prev=function(){this._isSliding||this._slide(h.PREV)},f.pause=function(t){t||(this._isPaused=!0),e(this._element).find(d.NEXT_PREV)[0]&&s.supportsTransitionEnd()&&(s.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},f.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},f.to=function(t){var n=this;this._activeElement=e(this._element).find(d.ACTIVE_ITEM)[0];var i=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)e(this._element).one(c.SLID,function(){return n.to(t)});else{if(i===t)return this.pause(),void this.cycle();var s=t>i?h.NEXT:h.PREV;this._slide(s,this._items[t])}},f.dispose=function(){e(this._element).off(i),e.removeData(this._element,n),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},f._getConfig=function(n){return n=e.extend({},a,n),s.typeCheckConfig(t,n,l),n},f._addEventListeners=function(){var t=this;this._config.keyboard&&e(this._element).on(c.KEYDOWN,function(e){return t._keydown(e)}),"hover"===this._config.pause&&(e(this._element).on(c.MOUSEENTER,function(e){return t.pause(e)}).on(c.MOUSELEAVE,function(e){return t.cycle(e)}),"ontouchstart"in document.documentElement&&e(this._element).on(c.TOUCHEND,function(){t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout(function(e){return t.cycle(e)},500+t._config.interval)}))},f._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next();break;default:return}},f._getItemIndex=function(t){return this._items=e.makeArray(e(t).parent().find(d.ITEM)),this._items.indexOf(t)},f._getItemByDirection=function(t,e){var n=t===h.NEXT,i=t===h.PREV,s=this._getItemIndex(e),r=this._items.length-1;if((i&&0===s||n&&s===r)&&!this._config.wrap)return e;var o=(s+(t===h.PREV?-1:1))%this._items.length;return-1===o?this._items[this._items.length-1]:this._items[o]},f._triggerSlideEvent=function(t,n){var i=this._getItemIndex(t),s=this._getItemIndex(e(this._element).find(d.ACTIVE_ITEM)[0]),r=e.Event(c.SLIDE,{relatedTarget:t,direction:n,from:s,to:i});return e(this._element).trigger(r),r},f._setActiveIndicatorElement=function(t){if(this._indicatorsElement){e(this._indicatorsElement).find(d.ACTIVE).removeClass(u.ACTIVE);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&e(n).addClass(u.ACTIVE)}},f._slide=function(t,n){var i,r,o,a=this,l=e(this._element).find(d.ACTIVE_ITEM)[0],f=this._getItemIndex(l),_=n||l&&this._getItemByDirection(t,l),g=this._getItemIndex(_),m=Boolean(this._interval);if(t===h.NEXT?(i=u.LEFT,r=u.NEXT,o=h.LEFT):(i=u.RIGHT,r=u.PREV,o=h.RIGHT),_&&e(_).hasClass(u.ACTIVE))this._isSliding=!1;else if(!this._triggerSlideEvent(_,o).isDefaultPrevented()&&l&&_){this._isSliding=!0,m&&this.pause(),this._setActiveIndicatorElement(_);var p=e.Event(c.SLID,{relatedTarget:_,direction:o,from:f,to:g});s.supportsTransitionEnd()&&e(this._element).hasClass(u.SLIDE)?(e(_).addClass(r),s.reflow(_),e(l).addClass(i),e(_).addClass(i),e(l).one(s.TRANSITION_END,function(){e(_).removeClass(i+" "+r).addClass(u.ACTIVE),e(l).removeClass(u.ACTIVE+" "+r+" "+i),a._isSliding=!1,setTimeout(function(){return e(a._element).trigger(p)},0)}).emulateTransitionEnd(600)):(e(l).removeClass(u.ACTIVE),e(_).addClass(u.ACTIVE),this._isSliding=!1,e(this._element).trigger(p)),m&&this.cycle()}},o._jQueryInterface=function(t){return this.each(function(){var i=e(this).data(n),s=e.extend({},a,e(this).data());"object"==typeof t&&e.extend(s,t);var r="string"==typeof t?t:s.slide;if(i||(i=new o(this,s),e(this).data(n,i)),"number"==typeof t)i.to(t);else if("string"==typeof r){if("undefined"==typeof i[r])throw new Error('No method named "'+r+'"');i[r]()}else s.interval&&(i.pause(),i.cycle())})},o._dataApiClickHandler=function(t){var i=s.getSelectorFromElement(this);if(i){var r=e(i)[0];if(r&&e(r).hasClass(u.CAROUSEL)){var a=e.extend({},e(r).data(),e(this).data()),l=this.getAttribute("data-slide-to");l&&(a.interval=!1),o._jQueryInterface.call(e(r),a),l&&e(r).data(n).to(l),t.preventDefault()}}},r(o,null,[{key:"VERSION",get:function(){return"4.0.0-beta.2"}},{key:"Default",get:function(){return a}}]),o}();return e(document).on(c.CLICK_DATA_API,d.DATA_SLIDE,f._dataApiClickHandler),e(window).on(c.LOAD_DATA_API,function(){e(d.DATA_RIDE).each(function(){var t=e(this);f._jQueryInterface.call(t,t.data())})}),e.fn[t]=f._jQueryInterface,e.fn[t].Constructor=f,e.fn[t].noConflict=function(){return e.fn[t]=o,f._jQueryInterface},f}(),c=function(){var t="collapse",n="bs.collapse",i=e.fn[t],o={toggle:!0,parent:""},a={toggle:"boolean",parent:"(string|element)"},l={SHOW:"show.bs.collapse",SHOWN:"shown.bs.collapse",HIDE:"hide.bs.collapse",HIDDEN:"hidden.bs.collapse",CLICK_DATA_API:"click.bs.collapse.data-api"},h={SHOW:"show",COLLAPSE:"collapse",COLLAPSING:"collapsing",COLLAPSED:"collapsed"},c={WIDTH:"width",HEIGHT:"height"},u={ACTIVES:".show, .collapsing",DATA_TOGGLE:'[data-toggle="collapse"]'},d=function(){function i(t,n){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(n),this._triggerArray=e.makeArray(e('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var i=e(u.DATA_TOGGLE),r=0;r0&&this._triggerArray.push(o)}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var d=i.prototype;return d.toggle=function(){e(this._element).hasClass(h.SHOW)?this.hide():this.show()},d.show=function(){var t=this;if(!this._isTransitioning&&!e(this._element).hasClass(h.SHOW)){var r,o;if(this._parent&&((r=e.makeArray(e(this._parent).children().children(u.ACTIVES))).length||(r=null)),!(r&&(o=e(r).data(n))&&o._isTransitioning)){var a=e.Event(l.SHOW);if(e(this._element).trigger(a),!a.isDefaultPrevented()){r&&(i._jQueryInterface.call(e(r),"hide"),o||e(r).data(n,null));var c=this._getDimension();e(this._element).removeClass(h.COLLAPSE).addClass(h.COLLAPSING),this._element.style[c]=0,this._triggerArray.length&&e(this._triggerArray).removeClass(h.COLLAPSED).attr("aria-expanded",!0),this.setTransitioning(!0);var d=function(){e(t._element).removeClass(h.COLLAPSING).addClass(h.COLLAPSE).addClass(h.SHOW),t._element.style[c]="",t.setTransitioning(!1),e(t._element).trigger(l.SHOWN)};if(s.supportsTransitionEnd()){var f="scroll"+(c[0].toUpperCase()+c.slice(1));e(this._element).one(s.TRANSITION_END,d).emulateTransitionEnd(600),this._element.style[c]=this._element[f]+"px"}else d()}}}},d.hide=function(){var t=this;if(!this._isTransitioning&&e(this._element).hasClass(h.SHOW)){var n=e.Event(l.HIDE);if(e(this._element).trigger(n),!n.isDefaultPrevented()){var i=this._getDimension();if(this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",s.reflow(this._element),e(this._element).addClass(h.COLLAPSING).removeClass(h.COLLAPSE).removeClass(h.SHOW),this._triggerArray.length)for(var r=0;r0},g._getPopperConfig=function(){var t=this,n={};"function"==typeof this._config.offset?n.fn=function(n){return n.offsets=e.extend({},n.offsets,t._config.offset(n.offsets)||{}),n}:n.offset=this._config.offset;var i={placement:this._getPlacement(),modifiers:{offset:n,flip:{enabled:this._config.flip}}};return this._inNavbar&&(i.modifiers.applyStyle={enabled:!this._inNavbar}),i},a._jQueryInterface=function(t){return this.each(function(){var n=e(this).data(i),s="object"==typeof t?t:null;if(n||(n=new a(this,s),e(this).data(i,n)),"string"==typeof t){if("undefined"==typeof n[t])throw new Error('No method named "'+t+'"');n[t]()}})},a._clearMenus=function(t){if(!t||3!==t.which&&("keyup"!==t.type||9===t.which))for(var n=e.makeArray(e(u.DATA_TOGGLE)),s=0;s0&&r--,40===t.which&&rdocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},u._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},u._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip"},u={SHOW:"show",OUT:"out"},d={HIDE:"hide"+i,HIDDEN:"hidden"+i,SHOW:"show"+i,SHOWN:"shown"+i,INSERTED:"inserted"+i,CLICK:"click"+i,FOCUSIN:"focusin"+i,FOCUSOUT:"focusout"+i,MOUSEENTER:"mouseenter"+i,MOUSELEAVE:"mouseleave"+i},f={FADE:"fade",SHOW:"show"},_={TOOLTIP:".tooltip",TOOLTIP_INNER:".tooltip-inner",ARROW:".arrow"},g={HOVER:"hover",FOCUS:"focus",CLICK:"click",MANUAL:"manual"},m=function(){function o(t,e){this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var m=o.prototype;return m.enable=function(){this._isEnabled=!0},m.disable=function(){this._isEnabled=!1},m.toggleEnabled=function(){this._isEnabled=!this._isEnabled},m.toggle=function(t){if(this._isEnabled)if(t){var n=this.constructor.DATA_KEY,i=e(t.currentTarget).data(n);i||(i=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(n,i)),i._activeTrigger.click=!i._activeTrigger.click,i._isWithActiveTrigger()?i._enter(null,i):i._leave(null,i)}else{if(e(this.getTipElement()).hasClass(f.SHOW))return void this._leave(null,this);this._enter(null,this)}},m.dispose=function(){clearTimeout(this._timeout),e.removeData(this.element,this.constructor.DATA_KEY),e(this.element).off(this.constructor.EVENT_KEY),e(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&e(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,null!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},m.show=function(){var t=this;if("none"===e(this.element).css("display"))throw new Error("Please use show on visible elements");var i=e.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){e(this.element).trigger(i);var r=e.contains(this.element.ownerDocument.documentElement,this.element);if(i.isDefaultPrevented()||!r)return;var a=this.getTipElement(),l=s.getUID(this.constructor.NAME);a.setAttribute("id",l),this.element.setAttribute("aria-describedby",l),this.setContent(),this.config.animation&&e(a).addClass(f.FADE);var h="function"==typeof this.config.placement?this.config.placement.call(this,a,this.element):this.config.placement,c=this._getAttachment(h);this.addAttachmentClass(c);var d=!1===this.config.container?document.body:e(this.config.container);e(a).data(this.constructor.DATA_KEY,this),e.contains(this.element.ownerDocument.documentElement,this.tip)||e(a).appendTo(d),e(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new n(this.element,a,{placement:c,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:_.ARROW}},onCreate:function(e){e.originalPlacement!==e.placement&&t._handlePopperPlacementChange(e)},onUpdate:function(e){t._handlePopperPlacementChange(e)}}),e(a).addClass(f.SHOW),"ontouchstart"in document.documentElement&&e("body").children().on("mouseover",null,e.noop);var g=function(){t.config.animation&&t._fixTransition();var n=t._hoverState;t._hoverState=null,e(t.element).trigger(t.constructor.Event.SHOWN),n===u.OUT&&t._leave(null,t)};s.supportsTransitionEnd()&&e(this.tip).hasClass(f.FADE)?e(this.tip).one(s.TRANSITION_END,g).emulateTransitionEnd(o._TRANSITION_DURATION):g()}},m.hide=function(t){var n=this,i=this.getTipElement(),r=e.Event(this.constructor.Event.HIDE),o=function(){n._hoverState!==u.SHOW&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),e(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),t&&t()};e(this.element).trigger(r),r.isDefaultPrevented()||(e(i).removeClass(f.SHOW),"ontouchstart"in document.documentElement&&e("body").children().off("mouseover",null,e.noop),this._activeTrigger[g.CLICK]=!1,this._activeTrigger[g.FOCUS]=!1,this._activeTrigger[g.HOVER]=!1,s.supportsTransitionEnd()&&e(this.tip).hasClass(f.FADE)?e(i).one(s.TRANSITION_END,o).emulateTransitionEnd(150):o(),this._hoverState="")},m.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},m.isWithContent=function(){return Boolean(this.getTitle())},m.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-tooltip-"+t)},m.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},m.setContent=function(){var t=e(this.getTipElement());this.setElementContent(t.find(_.TOOLTIP_INNER),this.getTitle()),t.removeClass(f.FADE+" "+f.SHOW)},m.setElementContent=function(t,n){var i=this.config.html;"object"==typeof n&&(n.nodeType||n.jquery)?i?e(n).parent().is(t)||t.empty().append(n):t.text(e(n).text()):t[i?"html":"text"](n)},m.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},m._getAttachment=function(t){return h[t.toUpperCase()]},m._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach(function(n){if("click"===n)e(t.element).on(t.constructor.Event.CLICK,t.config.selector,function(e){return t.toggle(e)});else if(n!==g.MANUAL){var i=n===g.HOVER?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,s=n===g.HOVER?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;e(t.element).on(i,t.config.selector,function(e){return t._enter(e)}).on(s,t.config.selector,function(e){return t._leave(e)})}e(t.element).closest(".modal").on("hide.bs.modal",function(){return t.hide()})}),this.config.selector?this.config=e.extend({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},m._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},m._enter=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusin"===t.type?g.FOCUS:g.HOVER]=!0),e(n.getTipElement()).hasClass(f.SHOW)||n._hoverState===u.SHOW?n._hoverState=u.SHOW:(clearTimeout(n._timeout),n._hoverState=u.SHOW,n.config.delay&&n.config.delay.show?n._timeout=setTimeout(function(){n._hoverState===u.SHOW&&n.show()},n.config.delay.show):n.show())},m._leave=function(t,n){var i=this.constructor.DATA_KEY;(n=n||e(t.currentTarget).data(i))||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),e(t.currentTarget).data(i,n)),t&&(n._activeTrigger["focusout"===t.type?g.FOCUS:g.HOVER]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState=u.OUT,n.config.delay&&n.config.delay.hide?n._timeout=setTimeout(function(){n._hoverState===u.OUT&&n.hide()},n.config.delay.hide):n.hide())},m._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},m._getConfig=function(n){return"number"==typeof(n=e.extend({},this.constructor.Default,e(this.element).data(),n)).delay&&(n.delay={show:n.delay,hide:n.delay}),"number"==typeof n.title&&(n.title=n.title.toString()),"number"==typeof n.content&&(n.content=n.content.toString()),s.typeCheckConfig(t,n,this.constructor.DefaultType),n},m._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},m._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(a);null!==n&&n.length>0&&t.removeClass(n.join(""))},m._handlePopperPlacementChange=function(t){this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},m._fixTransition=function(){var t=this.getTipElement(),n=this.config.animation;null===t.getAttribute("x-placement")&&(e(t).removeClass(f.FADE),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},o._jQueryInterface=function(t){return this.each(function(){var n=e(this).data("bs.tooltip"),i="object"==typeof t&&t;if((n||!/dispose|hide/.test(t))&&(n||(n=new o(this,i),e(this).data("bs.tooltip",n)),"string"==typeof t)){if("undefined"==typeof n[t])throw new Error('No method named "'+t+'"');n[t]()}})},r(o,null,[{key:"VERSION",get:function(){return"4.0.0-beta.2"}},{key:"Default",get:function(){return c}},{key:"NAME",get:function(){return t}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return d}},{key:"EVENT_KEY",get:function(){return i}},{key:"DefaultType",get:function(){return l}}]),o}();return e.fn[t]=m._jQueryInterface,e.fn[t].Constructor=m,e.fn[t].noConflict=function(){return e.fn[t]=o,m._jQueryInterface},m}(),_=function(){var t="popover",n=".bs.popover",i=e.fn[t],s=new RegExp("(^|\\s)bs-popover\\S+","g"),a=e.extend({},f.Default,{placement:"right",trigger:"click",content:"",template:''}),l=e.extend({},f.DefaultType,{content:"(string|element|function)"}),h={FADE:"fade",SHOW:"show"},c={TITLE:".popover-header",CONTENT:".popover-body"},u={HIDE:"hide"+n,HIDDEN:"hidden"+n,SHOW:"show"+n,SHOWN:"shown"+n,INSERTED:"inserted"+n,CLICK:"click"+n,FOCUSIN:"focusin"+n,FOCUSOUT:"focusout"+n,MOUSEENTER:"mouseenter"+n,MOUSELEAVE:"mouseleave"+n},d=function(i){function d(){return i.apply(this,arguments)||this}o(d,i);var f=d.prototype;return f.isWithContent=function(){return this.getTitle()||this._getContent()},f.addAttachmentClass=function(t){e(this.getTipElement()).addClass("bs-popover-"+t)},f.getTipElement=function(){return this.tip=this.tip||e(this.config.template)[0],this.tip},f.setContent=function(){var t=e(this.getTipElement());this.setElementContent(t.find(c.TITLE),this.getTitle()),this.setElementContent(t.find(c.CONTENT),this._getContent()),t.removeClass(h.FADE+" "+h.SHOW)},f._getContent=function(){return this.element.getAttribute("data-content")||("function"==typeof this.config.content?this.config.content.call(this.element):this.config.content)},f._cleanTipClass=function(){var t=e(this.getTipElement()),n=t.attr("class").match(s);null!==n&&n.length>0&&t.removeClass(n.join(""))},d._jQueryInterface=function(t){return this.each(function(){var n=e(this).data("bs.popover"),i="object"==typeof t?t:null;if((n||!/destroy|hide/.test(t))&&(n||(n=new d(this,i),e(this).data("bs.popover",n)),"string"==typeof t)){if("undefined"==typeof n[t])throw new Error('No method named "'+t+'"');n[t]()}})},r(d,null,[{key:"VERSION",get:function(){return"4.0.0-beta.2"}},{key:"Default",get:function(){return a}},{key:"NAME",get:function(){return t}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return u}},{key:"EVENT_KEY",get:function(){return n}},{key:"DefaultType",get:function(){return l}}]),d}(f);return e.fn[t]=d._jQueryInterface,e.fn[t].Constructor=d,e.fn[t].noConflict=function(){return e.fn[t]=i,d._jQueryInterface},d}(),g=function(){var t="scrollspy",n=e.fn[t],i={offset:10,method:"auto",target:""},o={offset:"number",method:"string",target:"(string|element)"},a={ACTIVATE:"activate.bs.scrollspy",SCROLL:"scroll.bs.scrollspy",LOAD_DATA_API:"load.bs.scrollspy.data-api"},l={DROPDOWN_ITEM:"dropdown-item",DROPDOWN_MENU:"dropdown-menu",ACTIVE:"active"},h={DATA_SPY:'[data-spy="scroll"]',ACTIVE:".active",NAV_LIST_GROUP:".nav, .list-group",NAV_LINKS:".nav-link",NAV_ITEMS:".nav-item",LIST_ITEMS:".list-group-item",DROPDOWN:".dropdown",DROPDOWN_ITEMS:".dropdown-item",DROPDOWN_TOGGLE:".dropdown-toggle"},c={OFFSET:"offset",POSITION:"position"},u=function(){function n(t,n){var i=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(n),this._selector=this._config.target+" "+h.NAV_LINKS+","+this._config.target+" "+h.LIST_ITEMS+","+this._config.target+" "+h.DROPDOWN_ITEMS,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,e(this._scrollElement).on(a.SCROLL,function(t){return i._process(t)}),this.refresh(),this._process()}var u=n.prototype;return u.refresh=function(){var t=this,n=this._scrollElement!==this._scrollElement.window?c.POSITION:c.OFFSET,i="auto"===this._config.method?n:this._config.method,r=i===c.POSITION?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),e.makeArray(e(this._selector)).map(function(t){var n,o=s.getSelectorFromElement(t);if(o&&(n=e(o)[0]),n){var a=n.getBoundingClientRect();if(a.width||a.height)return[e(n)[i]().top+r,o]}return null}).filter(function(t){return t}).sort(function(t,e){return t[0]-e[0]}).forEach(function(e){t._offsets.push(e[0]),t._targets.push(e[1])})},u.dispose=function(){e.removeData(this._element,"bs.scrollspy"),e(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},u._getConfig=function(n){if("string"!=typeof(n=e.extend({},i,n)).target){var r=e(n.target).attr("id");r||(r=s.getUID(t),e(n.target).attr("id",r)),n.target="#"+r}return s.typeCheckConfig(t,n,o),n},u._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},u._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},u._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},u._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var s=this._offsets.length;s--;)this._activeTarget!==this._targets[s]&&t>=this._offsets[s]&&("undefined"==typeof this._offsets[s+1]||t li > .active",DATA_TOGGLE:'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',DROPDOWN_TOGGLE:".dropdown-toggle",DROPDOWN_ACTIVE_CHILD:"> .dropdown-menu .active"},a=function(){function t(t){this._element=t}var a=t.prototype;return a.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&e(this._element).hasClass(i.ACTIVE)||e(this._element).hasClass(i.DISABLED))){var r,a,l=e(this._element).closest(o.NAV_LIST_GROUP)[0],h=s.getSelectorFromElement(this._element);if(l){var c="UL"===l.nodeName?o.ACTIVE_UL:o.ACTIVE;a=e.makeArray(e(l).find(c)),a=a[a.length-1]}var u=e.Event(n.HIDE,{relatedTarget:this._element}),d=e.Event(n.SHOW,{relatedTarget:a});if(a&&e(a).trigger(u),e(this._element).trigger(d),!d.isDefaultPrevented()&&!u.isDefaultPrevented()){h&&(r=e(h)[0]),this._activate(this._element,l);var f=function(){var i=e.Event(n.HIDDEN,{relatedTarget:t._element}),s=e.Event(n.SHOWN,{relatedTarget:a});e(a).trigger(i),e(t._element).trigger(s)};r?this._activate(r,r.parentNode,f):f()}}},a.dispose=function(){e.removeData(this._element,"bs.tab"),this._element=null},a._activate=function(t,n,r){var a,l=this,h=(a="UL"===n.nodeName?e(n).find(o.ACTIVE_UL):e(n).children(o.ACTIVE))[0],c=r&&s.supportsTransitionEnd()&&h&&e(h).hasClass(i.FADE),u=function(){return l._transitionComplete(t,h,c,r)};h&&c?e(h).one(s.TRANSITION_END,u).emulateTransitionEnd(150):u(),h&&e(h).removeClass(i.SHOW)},a._transitionComplete=function(t,n,r,a){if(n){e(n).removeClass(i.ACTIVE);var l=e(n.parentNode).find(o.DROPDOWN_ACTIVE_CHILD)[0];l&&e(l).removeClass(i.ACTIVE),"tab"===n.getAttribute("role")&&n.setAttribute("aria-selected",!1)}if(e(t).addClass(i.ACTIVE),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),r?(s.reflow(t),e(t).addClass(i.SHOW)):e(t).removeClass(i.FADE),t.parentNode&&e(t.parentNode).hasClass(i.DROPDOWN_MENU)){var h=e(t).closest(o.DROPDOWN)[0];h&&e(h).find(o.DROPDOWN_TOGGLE).addClass(i.ACTIVE),t.setAttribute("aria-expanded",!0)}a&&a()},t._jQueryInterface=function(n){return this.each(function(){var i=e(this),s=i.data("bs.tab");if(s||(s=new t(this),i.data("bs.tab",s)),"string"==typeof n){if("undefined"==typeof s[n])throw new Error('No method named "'+n+'"');s[n]()}})},r(t,null,[{key:"VERSION",get:function(){return"4.0.0-beta.2"}}]),t}();return e(document).on(n.CLICK_DATA_API,o.DATA_TOGGLE,function(t){t.preventDefault(),a._jQueryInterface.call(e(this),"show")}),e.fn.tab=a._jQueryInterface,e.fn.tab.Constructor=a,e.fn.tab.noConflict=function(){return e.fn.tab=t,a._jQueryInterface},a}();return function(){if("undefined"==typeof e)throw new Error("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||t[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(),t.Util=s,t.Alert=a,t.Button=l,t.Carousel=h,t.Collapse=c,t.Dropdown=u,t.Modal=d,t.Popover=_,t.Scrollspy=g,t.Tab=m,t.Tooltip=f,t}({},$,Popper); +//# sourceMappingURL=bootstrap.min.js.map \ No newline at end of file diff --git a/Documents/js/diaghome.js b/Documents/js/diaghome.js index d51233bed..9d95d9edd 100644 --- a/Documents/js/diaghome.js +++ b/Documents/js/diaghome.js @@ -1,30 +1,37 @@ -var hdrHeight = $("#top-hdr").height(); -var hdrHeightPx = hdrHeight + 5 + "px"; - -$("body").animate({ - paddingTop: hdrHeightPx, - duration: 'fast' -}); - -$("#rfrshBtn").click(function() { - window.location.reload(true); -}); - -$("#rfrshBtn").hover(function(e) { - $("#rfrshBtnIcn").toggleClass("fa-spin"); -}); - -$(window).scroll(function() { - if ($("body").scrollTop() > 20 || document.documentElement.scrollTop > 20) { - $("#scrollTopBtn").css({ - display: "block" - }); - } else { - $("#scrollTopBtn").css({ - display: "none" - }); - } -}); +'use esversion: 6'; + +var copyBtn = document.getElementById('copyUrlBtn'); +var clipboard = new Clipboard('.copyBtn'); + +function makeRequest(url, method, message, contentType, responseType) { + return new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + // url += appId || ''; + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.DONE) { + if (xhr.status === 200) { + resolve(xhr.response); + } else { + reject(Error(xhr.statusText)); + } + } + }; + xhr.onprogress = function() { + // console.log('LOADING', xhr.readyState); // readyState will be 3 + }; + xhr.onerror = function() { + reject(Error('XMLHttpRequest failed; error code:' + xhr.statusText)); + }; + xhr.open(method, url, true); + if (contentType !== null && responseType !== null) { + xhr.setRequestHeader('Accept', contentType); + xhr.responseType = responseType; + xhr.send(); + } else { + xhr.send(message); + } + }); +} function topFunction() { //console.log("requested height:", hdrHeightPx, "| actual height:", $('body').scrollTop()); @@ -32,28 +39,12 @@ function topFunction() { document.documentElement.scrollTop = hdrHeightPx; } -$(function() { - $("#stateUseCirc").percircle(); -}); - - - -var btn = document.getElementById('copyUrlBtn'); -var clipboard = new Clipboard('.btn'); - -clipboard.on('success', function(e) { - console.info('Text:', e.text); - //console.info('Trigger:', e.trigger); - e.clearSelection(); -}); - -clipboard.on('error', function(e) { - //console.error('Action:', e.action); - //console.error('Trigger:', e.trigger); -}); +var hdrHeight = $("#top-hdr").height(); +var hdrHeightPx = hdrHeight + 5 + "px"; $("body").animate({ - paddingTop: hdrHeightPx + paddingTop: hdrHeightPx, + duration: 'fast' }); $("#rfrshBtn").click(function() { @@ -64,55 +55,52 @@ $("#rfrshBtn").hover(function(e) { $("#rfrshBtnIcn").toggleClass("fa-spin"); }); -$(window).scroll(function() { - if ($("body").scrollTop() > 20 || document.documentElement.scrollTop > 20) { - $("#scrollTopBtn").css({ - display: "block" +$('#stateCleanupBtn').click(function(e) { + var data = JSON.stringify({ + cmd: "stateCleanup", + value: null + }); + makeRequest(cmdUrl, 'POST', data, null, null) + .catch(function(err) { + console.log(err, 'Diag Command Results!'); + }) + .then(function(resp) { + if (JSON.parse(resp).data) { + console.log("diagCmd: Sent Successfully!"); + } }); - } else { - $("#scrollTopBtn").css({ - display: "none" - }); - } -}); - -function topFunction() { - //console.log("requested height:", hdrHeightPx, "| actual height:", $('body').scrollTop()); - document.body.scrollTop = hdrHeightPx; - document.documentElement.scrollTop = hdrHeightPx; -} - -$(function() { - $("#stateUseCirc").percircle(); -}); - - - -var btn = document.getElementById('copyUrlBtn'); -var clipboard = new Clipboard('.btn'); - -clipboard.on('success', function(e) { - console.info('Text:', e.text); - //console.info('Trigger:', e.trigger); - e.clearSelection(); }); -clipboard.on('error', function(e) { - //console.error('Action:', e.action); - //console.error('Trigger:', e.trigger); -}); - -$("body").animate({ - paddingTop: hdrHeightPx, - duration: 'fast' -}); - -$("#rfrshBtn").click(function() { - window.location.reload(true); +$('#updateMethodBtn').click(function(e) { + var data = JSON.stringify({ + cmd: "runUpdated", + value: null + }); + makeRequest(cmdUrl, 'POST', data, null, null) + .catch(function(err) { + console.log(err, 'Diag Command Results!'); + }) + .then(function(resp) { + if (JSON.parse(resp).gotData) { + console.log("diagCmd: Sent Successfully!"); + } + }); }); -$("#rfrshBtn").hover(function(e) { - $("#rfrshBtnIcn").toggleClass("fa-spin"); +$('#sendInstallDataBtn').click(function(e) { + var data = JSON.stringify({ + cmd: "sendFirebaseData", + value: null + }); + makeRequest(cmdUrl, 'POST', data, null, null) + .catch(function(err) { + console.log(err, 'Diag Command Results!'); + }) + .then(function(resp) { + if (JSON.parse(resp).gotData) { + console.log("diagCmd: Sent Successfully!"); + } + }); }); $(window).scroll(function() { @@ -127,21 +115,11 @@ $(window).scroll(function() { } }); -function topFunction() { - //console.log("requested height:", hdrHeightPx, "| actual height:", $('body').scrollTop()); - document.body.scrollTop = hdrHeightPx; - document.documentElement.scrollTop = hdrHeightPx; -} $(function() { $("#stateUseCirc").percircle(); }); - - -var btn = document.getElementById('copyUrlBtn'); -var clipboard = new Clipboard('.btn'); - clipboard.on('success', function(e) { console.info('Text:', e.text); //console.info('Trigger:', e.trigger); @@ -151,4 +129,4 @@ clipboard.on('success', function(e) { clipboard.on('error', function(e) { //console.error('Action:', e.action); //console.error('Trigger:', e.trigger); -}); +}); \ No newline at end of file diff --git a/Documents/js/diaghome.min.js b/Documents/js/diaghome.min.js index ecb037d34..1006065eb 100644 --- a/Documents/js/diaghome.min.js +++ b/Documents/js/diaghome.min.js @@ -1 +1 @@ -var hdrHeight=$("#top-hdr").height();var hdrHeightPx=hdrHeight+5+"px";$("body").animate({paddingTop:hdrHeightPx,duration:"fast"});$("#rfrshBtn").click(function(){window.location.reload(true)});$("#rfrshBtn").hover(function(a){$("#rfrshBtnIcn").toggleClass("fa-spin")});$(window).scroll(function(){if($("body").scrollTop()>20||document.documentElement.scrollTop>20){$("#scrollTopBtn").css({display:"block"})}else{$("#scrollTopBtn").css({display:"none"})}});function topFunction(){document.body.scrollTop=hdrHeightPx;document.documentElement.scrollTop=hdrHeightPx}$(function(){$("#stateUseCirc").percircle()});var btn=document.getElementById("copyUrlBtn");var clipboard=new Clipboard(".btn");clipboard.on("success",function(a){console.info("Text:",a.text);a.clearSelection()});clipboard.on("error",function(a){}); \ No newline at end of file +"use esversion: 6";function makeRequest(n,e,t,o,l){return new Promise(function(c,s){var r=new XMLHttpRequest;r.onreadystatechange=function(){r.readyState===XMLHttpRequest.DONE&&(200===r.status?c(r.response):s(Error(r.statusText)))},r.onprogress=function(){},r.onerror=function(){s(Error("XMLHttpRequest failed; error code:"+r.statusText))},r.open(e,n,!0),null!==o&&null!==l?(r.setRequestHeader("Accept",o),r.responseType=l,r.send()):r.send(t)})}function topFunction(){document.body.scrollTop=hdrHeightPx,document.documentElement.scrollTop=hdrHeightPx}var copyBtn=document.getElementById("copyUrlBtn"),clipboard=new Clipboard(".copyBtn"),hdrHeight=$("#top-hdr").height(),hdrHeightPx=hdrHeight+5+"px";$("body").animate({paddingTop:hdrHeightPx,duration:"fast"}),$("#rfrshBtn").click(function(){window.location.reload(!0)}),$("#rfrshBtn").hover(function(n){$("#rfrshBtnIcn").toggleClass("fa-spin")}),$("#stateCleanupBtn").click(function(n){var e=JSON.stringify({cmd:"stateCleanup",value:null});makeRequest(cmdUrl,"POST",e,null,null).catch(function(n){console.log(n,"Diag Command Results!")}).then(function(n){JSON.parse(n).data&&console.log("diagCmd: Sent Successfully!")})}),$("#updateMethodBtn").click(function(n){var e=JSON.stringify({cmd:"runUpdated",value:null});makeRequest(cmdUrl,"POST",e,null,null).catch(function(n){console.log(n,"Diag Command Results!")}).then(function(n){JSON.parse(n).gotData&&console.log("diagCmd: Sent Successfully!")})}),$("#sendInstallDataBtn").click(function(n){var e=JSON.stringify({cmd:"sendFirebaseData",value:null});makeRequest(cmdUrl,"POST",e,null,null).catch(function(n){console.log(n,"Diag Command Results!")}).then(function(n){JSON.parse(n).gotData&&console.log("diagCmd: Sent Successfully!")})}),$(window).scroll(function(){$("body").scrollTop()>20||document.documentElement.scrollTop>20?$("#scrollTopBtn").css({display:"block"}):$("#scrollTopBtn").css({display:"none"})}),$(function(){$("#stateUseCirc").percircle()}),clipboard.on("success",function(n){console.info("Text:",n.text),n.clearSelection()}),clipboard.on("error",function(n){}); \ No newline at end of file diff --git a/Documents/js/lodash.js b/Documents/js/lodash.js new file mode 100644 index 000000000..b39ddce69 --- /dev/null +++ b/Documents/js/lodash.js @@ -0,0 +1,17084 @@ +/** + * @license + * Lodash + * Copyright JS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.17.4'; + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', + FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256, + WRAP_FLIP_FLAG = 512; + + /** Used as default options for `_.truncate`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 800, + HOT_SPAN = 16; + + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 1, + LAZY_MAP_FLAG = 2, + LAZY_WHILE_FLAG = 3; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, + MAX_INTEGER = 1.7976931348623157e+308, + NAN = 0 / 0; + + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', WRAP_ARY_FLAG], + ['bind', WRAP_BIND_FLAG], + ['bindKey', WRAP_BIND_KEY_FLAG], + ['curry', WRAP_CURRY_FLAG], + ['curryRight', WRAP_CURRY_RIGHT_FLAG], + ['flip', WRAP_FLIP_FLAG], + ['partial', WRAP_PARTIAL_FLAG], + ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], + ['rearg', WRAP_REARG_FLAG] + ]; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + domExcTag = '[object DOMException]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + nullTag = '[object Null]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + undefinedTag = '[object Undefined]', + weakMapTag = '[object WeakMap]', + weakSetTag = '[object WeakSet]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to match empty string literals in compiled template source. */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + + /** Used to match leading and trailing whitespace. */ + var reTrim = /^\s+|\s+$/g, + reTrimStart = /^\s+/, + reTrimEnd = /\s+$/; + + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, + reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** + * Used to match + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match `RegExp` flags from their coerced string values. */ + var reFlags = /\w*$/; + + /** Used to detect bad signed hexadecimal string values. */ + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + + /** Used to detect binary string values. */ + var reIsBinary = /^0b[01]+$/i; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used to detect octal string values. */ + var reIsOctal = /^0o[0-7]+$/i; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + + /** Used to ensure capturing order of template delimiters. */ + var reNoMatch = /($^)/; + + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to compose unicode character classes. */ + var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + + /** Used to compose unicode capture groups. */ + var rsApos = "['\u2019]", + rsAstral = '[' + rsAstralRange + ']', + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + + /** Used to compose unicode regexes. */ + var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', + rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsOrdLower = '\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)', + rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + + /** Used to match apostrophes. */ + var reApos = RegExp(rsApos, 'g'); + + /** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ + var reComboMark = RegExp(rsCombo, 'g'); + + /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + + /** Used to match complex or compound words. */ + var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', + rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, + rsUpper + '+' + rsOptContrUpper, + rsOrdUpper, + rsOrdLower, + rsDigits, + rsEmoji + ].join('|'), 'g'); + + /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + + /** Used to detect strings that need a more robust regexp to match words. */ + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + + /** Used to assign default `context` object properties. */ + var contextProps = [ + 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + ]; + + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[weakMapTag] = false; + + /** Used to map Latin Unicode letters to basic Latin letters. */ + var deburredLetters = { + // Latin-1 Supplement block. + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' + }; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" + }; + + /** Used to escape characters for inclusion in compiled string literals. */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /** Built-in method references without a dependency on `root`. */ + var freeParseFloat = parseFloat, + freeParseInt = parseInt; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} + }()); + + /* Node.js helper references. */ + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, + nodeIsDate = nodeUtil && nodeUtil.isDate, + nodeIsMap = nodeUtil && nodeUtil.isMap, + nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, + nodeIsSet = nodeUtil && nodeUtil.isSet, + nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /*--------------------------------------------------------------------------*/ + + /** + * Adds the key-value `pair` to `map`. + * + * @private + * @param {Object} map The map to modify. + * @param {Array} pair The key-value pair to add. + * @returns {Object} Returns `map`. + */ + function addMapEntry(map, pair) { + // Don't return `map.set` because it's not chainable in IE 11. + map.set(pair[0], pair[1]); + return map; + } + + /** + * Adds `value` to `set`. + * + * @private + * @param {Object} set The set to modify. + * @param {*} value The value to add. + * @returns {Object} Returns `set`. + */ + function addSetEntry(set, value) { + // Don't return `set.add` because it's not chainable in IE 11. + set.add(value); + return set; + } + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + /** + * A specialized version of `baseAggregator` for arrays. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; + } + + /** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.forEachRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, iteratee) { + var length = array == null ? 0 : array.length; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + + /** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludes(array, value) { + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf(array, value, 0) > -1; + } + + /** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; + } + + /** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + /** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array == null ? 0 : array.length; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + + /** + * A specialized version of `_.reduceRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array == null ? 0 : array.length; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + + /** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + + /** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + var asciiSize = baseProperty('length'); + + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } + + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + + /** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); + } + + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ + function baseIsNaN(value) { + return value !== value; + } + + /** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ + function baseMean(array, iteratee) { + var length = array == null ? 0 : array.length; + return length ? (baseSum(array, iteratee) / length) : NAN; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ + function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + + /** + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ + function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } + return result; + } + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + /** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); + } + + /** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function cacheHas(cache, key) { + return cache.has(key); + } + + /** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ + function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ + function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ + function countHolders(array, placeholder) { + var length = array.length, + result = 0; + + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } + + /** + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. + * + * @private + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. + */ + var deburrLetter = basePropertyOf(deburredLetters); + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; + } + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ + function hasUnicode(string) { + return reHasUnicode.test(string); + } + + /** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + + /** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ + function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } + + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + + /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + /** + * Gets the number of symbols in `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ + function stringSize(string) { + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); + } + + /** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Create a new pristine `lodash` function using the `context` object. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Util + * @param {Object} [context=root] The context object. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'foo': _.constant('foo') }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'bar': lodash.constant('bar') }); + * + * _.isFunction(_.foo); + * // => true + * _.isFunction(_.bar); + * // => false + * + * lodash.isFunction(lodash.foo); + * // => false + * lodash.isFunction(lodash.bar); + * // => true + * + * // Create a suped-up `defer` in Node.js. + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; + */ + var runInContext = (function runInContext(context) { + context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); + + /** Built-in constructor references. */ + var Array = context.Array, + Date = context.Date, + Error = context.Error, + Function = context.Function, + Math = context.Math, + Object = context.Object, + RegExp = context.RegExp, + String = context.String, + TypeError = context.TypeError; + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = context['__core-js_shared__']; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Buffer = moduleExports ? context.Buffer : undefined, + Symbol = context.Symbol, + Uint8Array = context.Uint8Array, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), + objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, + symIterator = Symbol ? Symbol.iterator : undefined, + symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, + nativeIsFinite = context.isFinite, + nativeJoin = arrayProto.join, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max, + nativeMin = Math.min, + nativeNow = Date.now, + nativeParseInt = context.parseInt, + nativeRandom = Math.random, + nativeReverse = arrayProto.reverse; + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(context, 'DataView'), + Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), + Set = getNative(context, 'Set'), + WeakMap = getNative(context, 'WeakMap'), + nativeCreate = getNative(Object, 'create'); + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /** Used to lookup unminified function names. */ + var realNames = {}; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ + function baseLodash() { + // No operation performed. + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; + } + + /** + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB) as well as ES2015 template strings. Change the + * following template settings to use alternative delimiters. + * + * @static + * @memberOf _ + * @type {Object} + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'escape': reEscape, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'evaluate': reEvaluate, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type {string} + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type {Object} + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type {Function} + */ + '_': lodash + } + }; + + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + + /** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = copyArray(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = copyArray(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = copyArray(this.__views__); + return result; + } + + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), + isRight = dir < 0, + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), + start = view.start, + end = view.end, + length = end - start, + index = isRight ? end : (start - 1), + iteratees = this.__iteratees__, + iterLength = iteratees.length, + resIndex = 0, + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || (!isRight && arrLength == length && takeCount == length)) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + type = data.type, + computed = iteratee(value); + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } + } + + /** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } + + /** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ + function setCacheHas(value) { + return this.__data__.has(value); + } + + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `_.sample` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); + } + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + + /** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * Aggregates elements of `collection` on `accumulator` with keys transformed + * by `iteratee` and values set by `setter`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function baseAggregator(collection, setter, iteratee, accumulator) { + baseEach(collection, function(value, key, collection) { + setter(accumulator, value, iteratee(value), collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + + /** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + /** + * The base implementation of `_.at` without support for individual paths. + * + * @private + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths to pick. + * @returns {Array} Returns the picked elements. + */ + function baseAt(object, paths) { + var index = -1, + length = paths.length, + result = Array(length), + skip = object == null; + + while (++index < length) { + result[index] = skip ? undefined : get(object, paths[index]); + } + return result; + } + + /** + * The base implementation of `_.clamp` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ + function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; + } + + /** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, baseClone, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; + } + + /** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + */ + function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; + } + + /** + * The base implementation of `_.conformsTo` which accepts `props` to check. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + */ + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ + function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee == null ? value : iteratee(value); + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.forEachRight` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEachRight = createBaseEach(baseForOwnRight, true); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseForRight = createBaseFor(true); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return object && baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); + } + + /** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHasIn(object, key) { + return object != null && key in Object(object); + } + + /** + * The base implementation of `_.inRange` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ + function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); + } + + /** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + seen = caches[0]; + + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ + function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; + } + + /** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ + function baseInvoke(object, path, args) { + path = castPath(path, object); + object = parent(object, path); + var func = object == null ? object : object[toKey(last(path))]; + return func == null ? undefined : apply(func, object, args); + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } + + /** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ + function baseIsArrayBuffer(value) { + return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; + } + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); + } + + /** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; + } + + /** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) + : result + )) { + return false; + } + } + } + return true; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + + /** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); + } + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; + } + + /** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); + }; + } + + /** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + if (isObject(srcValue)) { + stack || (stack = new Stack); + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(object[key], srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = object[key], + srcValue = source[key], + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); + } + + /** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; + } + + /** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ + function baseOrderBy(collection, iteratees, orders) { + var index = -1; + iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, paths) { + return basePickBy(object, paths, function(value, path) { + return hasIn(object, path); + }); + } + + /** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ + function basePickBy(object, paths, predicate) { + var index = -1, + length = paths.length, + result = {}; + + while (++index < length) { + var path = paths[index], + value = baseGet(object, path); + + if (predicate(value, path)) { + baseSet(result, castPath(path, object), value); + } + } + return result; + } + + /** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; + } + + /** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; + + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } else { + baseUnset(array, index); + } + } + } + return array; + } + + /** + * The base implementation of `_.random` without support for returning + * floating-point numbers. + * + * @private + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the random number. + */ + function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); + } + + /** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the range of numbers. + */ + function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; + } + + /** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ + function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ + function baseSample(collection) { + return arraySample(values(collection)); + } + + /** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + + /** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; + } + + /** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + /** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndex(array, value, retHighest) { + var low = 0, + high = array == null ? low : array.length; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); + } + + /** + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The iteratee invoked per element. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + + var low = 0, + high = array == null ? 0 : array.length, + valIsNaN = value !== value, + valIsNull = value === null, + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); + + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseSortedUniq(array, iteratee) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; + } + } + return result; + } + + /** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ + function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The property path to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ + function baseUnset(object, path) { + path = castPath(path, object); + object = parent(object, path); + return object == null || delete object[toKey(last(path))]; + } + + /** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); + } + + /** + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && + predicate(array[index], index, array)) {} + + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ + function baseXor(arrays, iteratee, comparator) { + var length = arrays.length; + if (length < 2) { + return length ? baseUniq(arrays[0]) : []; + } + var index = -1, + result = Array(length); + + while (++index < length) { + var array = arrays[index], + othIndex = -1; + + while (++othIndex < length) { + if (othIndex != index) { + result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); + } + } + } + return baseUniq(baseFlatten(result, 1), iteratee, comparator); + } + + /** + * This base implementation of `_.zipObject` which assigns values using `assignFunc`. + * + * @private + * @param {Array} props The property identifiers. + * @param {Array} values The property values. + * @param {Function} assignFunc The function to assign values. + * @returns {Object} Returns the new object. + */ + function baseZipObject(props, values, assignFunc) { + var index = -1, + length = props.length, + valsLength = values.length, + result = {}; + + while (++index < length) { + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); + } + return result; + } + + /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + + /** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ + function castFunction(value) { + return typeof value == 'function' ? value : identity; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); + } + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + /** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); + } + + /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + /** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + + /** + * Creates a clone of `map`. + * + * @private + * @param {Object} map The map to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned map. + */ + function cloneMap(map, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map); + return arrayReduce(array, addMapEntry, new map.constructor); + } + + /** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ + function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; + } + + /** + * Creates a clone of `set`. + * + * @private + * @param {Object} set The set to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned set. + */ + function cloneSet(set, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set); + return arrayReduce(array, addSetEntry, new set.constructor); + } + + /** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ + function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; + } + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ + function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; + + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + + /** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); + } + + /** + * Creates a function like `_.groupBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} [initializer] The accumulator object initializer. + * @returns {Function} Returns the new aggregator function. + */ + function createAggregator(setter, initializer) { + return function(collection, iteratee) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, + accumulator = initializer ? initializer() : {}; + + return func(collection, setter, getIteratee(iteratee, 2), accumulator); + }; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } + + /** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ + function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = hasUnicode(string) + ? stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; + } + + /** + * Creates a function like `_.camelCase`. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ + function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : undefined; + + if (data && isLaziable(data[0]) && + data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && + !data[4].length && data[9] == 1 + ) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); + } + } + return function() { + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value)) { + return wrapper.plant(value).value(); + } + var index = 0, + result = length ? funcs[index].apply(this, args) : value; + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }); + } + + /** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & WRAP_ARY_FLAG, + isBind = bitmask & WRAP_BIND_FLAG, + isBindKey = bitmask & WRAP_BIND_KEY_FLAG, + isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), + isFlip = bitmask & WRAP_FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ + function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; + } + + /** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; + } + + /** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new over function. + */ + function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); + } + + /** + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. + * + * @private + * @param {number} length The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padding for `string`. + */ + function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); + + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ + function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); + return baseRange(start, end, step, fromRight); + }; + } + + /** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + + /** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); + + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; + + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); + } + + /** + * Creates a function like `_.round`. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); + if (precision) { + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); + } + return func(number); + }; + } + + /** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ + var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { + return new Set(values); + }; + + /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); + + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] === undefined + ? (isBindKey ? 0 : func.length) + : nativeMax(newData[9] - length, 0); + + if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { + bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == WRAP_BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); + } + + /** + * Used by `_.defaults` to customize its `_.assignIn` use to assign properties + * of source objects to the destination object for all destination properties + * that resolve to `undefined`. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source + * objects into destination objects that are passed thru. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ + function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); + stack['delete'](srcValue); + } + return objValue; + } + + /** + * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain + * objects. + * + * @private + * @param {*} value The value to inspect. + * @param {string} key The key of the property to inspect. + * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. + */ + function customOmitClone(value) { + return isPlainObject(value) ? undefined : value; + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked && stack.get(other)) { + return stacked == other; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked && stack.get(other)) { + return stacked == other; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty.call(realNames, result) ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + + /** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; + return object.placeholder; + } + + /** + * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, + * this function returns the custom method, otherwise it returns `baseIteratee`. + * If arguments are provided, the chosen function is invoked with them and + * its result is returned. + * + * @private + * @param {*} [value] The value to convert to an iteratee. + * @param {number} [arity] The arity of the created iteratee. + * @returns {Function} Returns the chosen function or its result. + */ + function getIteratee() { + var result = lodash.iteratee || iteratee; + result = result === iteratee ? baseIteratee : result; + return arguments.length ? result(arguments[0], arguments[1]) : result; + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ + function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; + } + + /** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; + + /** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; + }; + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} transforms The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms.length; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; + } + + /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + + /** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ + function hasPath(object, path, hasFunc) { + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); + } + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, cloneFunc, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return cloneMap(object, isDeep, cloneFunc); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return cloneSet(object, isDeep, cloneFunc); + + case symbolTag: + return cloneSymbol(object); + } + } + + /** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ + var isMaskable = coreJsData ? isFunction : stubFalse; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + /** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ + function isStrictComparable(value) { + return value === value && !isObject(value); + } + + /** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; + } + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); + + var isCombo = + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & WRAP_BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & WRAP_ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + /** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ + function parent(object, path) { + return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); + } + + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = copyArray(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = shortOut(baseSetData); + + /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + /** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoizeCapped(function(string) { + var result = []; + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements split into groups the length of `size`. + * If `array` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array == null ? 0 : array.length; + if (!length || size < 1) { + return []; + } + var index = 0, + resIndex = 0, + result = Array(nativeCeil(length / size)); + + while (index < length) { + result[resIndex++] = baseSlice(array, index, (index += size)); + } + return result; + } + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ + var difference = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] + * + * // The `_.property` iteratee shorthand. + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var differenceBy = baseRest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ + var differenceWith = baseRest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) + : []; + }); + + /** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function drop(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function dropRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // The `_.matches` iteratee shorthand. + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // The `_.property` iteratee shorthand. + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true, true) + : []; + } + + /** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true) + : []; + } + + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] + */ + function fill(array, value, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); + } + + /** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // The `_.matches` iteratee shorthand. + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // The `_.property` iteratee shorthand. + * _.findLastIndex(users, 'active'); + * // => 0 + */ + function findLastIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Recursively flatten `array` up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Array + * @param {Array} array The array to flatten. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * var array = [1, [2, [3, [4]], 5]]; + * + * _.flattenDepth(array, 1); + * // => [1, 2, [3, [4]], 5] + * + * _.flattenDepth(array, 2); + * // => [1, 2, 3, [4], 5] + */ + function flattenDepth(array, depth) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(array, depth); + } + + /** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } + */ + function fromPairs(pairs) { + var index = -1, + length = pairs == null ? 0 : pairs.length, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + result[pair[0]] = pair[1]; + } + return result; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); + } + + /** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ + function initial(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 0, -1) : []; + } + + /** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [2.1] + * + * // The `_.property` iteratee shorthand. + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ + var intersectionBy = baseRest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ + var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + comparator = typeof comparator == 'function' ? comparator : undefined; + if (comparator) { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; + }); + + /** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ + function join(array, separator) { + return array == null ? '' : nativeJoin.call(array, separator); + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; + } + + /** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // Search from the `fromIndex`. + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); + } + + /** + * Gets the element at index `n` of `array`. If `n` is negative, the nth + * element from the end is returned. + * + * @static + * @memberOf _ + * @since 4.11.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=0] The index of the element to return. + * @returns {*} Returns the nth element of `array`. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * + * _.nth(array, 1); + * // => 'b' + * + * _.nth(array, -2); + * // => 'c'; + */ + function nth(array, n) { + return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; + } + + /** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ + var pull = baseRest(pullAll); + + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ + function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `iteratee` which is + * invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The iteratee is invoked with one argument: (value). + * + * **Note:** Unlike `_.differenceBy`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; + * + * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); + * console.log(array); + * // => [{ 'x': 2 }] + */ + function pullAllBy(array, values, iteratee) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, getIteratee(iteratee, 2)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) + : array; + } + + /** + * Removes elements from `array` corresponding to `indexes` and returns an + * array of removed elements. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * var pulled = _.pullAt(array, [1, 3]); + * + * console.log(array); + * // => ['a', 'c'] + * + * console.log(pulled); + * // => ['b', 'd'] + */ + var pullAt = flatRest(function(array, indexes) { + var length = array == null ? 0 : array.length, + result = baseAt(array, indexes); + + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); + + return result; + }); + + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is invoked + * with three arguments: (value, index, array). + * + * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` + * to pull elements from an array by value. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove(array, predicate) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, + indexes = [], + length = array.length; + + predicate = getIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + + /** + * Reverses `array` so that the first element becomes the last, the second + * element becomes the second to last, and so on. + * + * **Note:** This method mutates `array` and is based on + * [`Array#reverse`](https://mdn.io/Array/reverse). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.reverse(array); + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function reverse(array) { + return array == null ? array : nativeReverse.call(array); + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + else { + start = start == null ? 0 : toInteger(start); + end = end === undefined ? length : toInteger(end); + } + return baseSlice(array, start, end); + } + + /** + * Uses a binary search to determine the lowest index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + */ + function sortedIndex(array, value) { + return baseSortedIndex(array, value); + } + + /** + * This method is like `_.sortedIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); + * // => 0 + */ + function sortedIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); + } + + /** + * This method is like `_.indexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedIndexOf([4, 5, 5, 5, 6], 5); + * // => 1 + */ + function sortedIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedLastIndex([4, 5, 5, 5, 6], 5); + * // => 4 + */ + function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); + } + + /** + * This method is like `_.sortedLastIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 1 + * + * // The `_.property` iteratee shorthand. + * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); + * // => 1 + */ + function sortedLastIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); + } + + /** + * This method is like `_.lastIndexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); + * // => 3 + */ + function sortedLastIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.uniq` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniq([1, 1, 2]); + * // => [1, 2] + */ + function sortedUniq(array) { + return (array && array.length) + ? baseSortedUniq(array) + : []; + } + + /** + * This method is like `_.uniqBy` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); + * // => [1.1, 2.3] + */ + function sortedUniqBy(array, iteratee) { + return (array && array.length) + ? baseSortedUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * Gets all but the first element of `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.tail([1, 2, 3]); + * // => [2, 3] + */ + function tail(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 1, length) : []; + } + + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + function take(array, n, guard) { + if (!(array && array.length)) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3]); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + function takeRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.takeRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeRightWhile(users, ['active', false]); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.takeRightWhile(users, 'active'); + * // => [] + */ + function takeRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), false, true) + : []; + } + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.takeWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matches` iteratee shorthand. + * _.takeWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeWhile(users, ['active', false]); + * // => objects for ['barney', 'fred'] + * + * // The `_.property` iteratee shorthand. + * _.takeWhile(users, 'active'); + * // => [] + */ + function takeWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3)) + : []; + } + + /** + * Creates an array of unique values, in order, from all given arrays using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([2], [1, 2]); + * // => [2, 1] + */ + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); + }); + + /** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + var unionBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.union` except that it accepts `comparator` which + * is invoked to compare elements of `arrays`. Result values are chosen from + * the first array in which the value occurs. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.unionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var unionWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); + }); + + /** + * Creates a duplicate-free version of an array, using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniq([2, 1, 2]); + * // => [2, 1] + */ + function uniq(array) { + return (array && array.length) ? baseUniq(array) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniqBy([2.1, 1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniqBy(array, iteratee) { + return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.uniqWith(objects, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ + function uniqWith(array, comparator) { + comparator = typeof comparator == 'function' ? comparator : undefined; + return (array && array.length) ? baseUniq(array, undefined, comparator) : []; + } + + /** + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-zip + * configuration. + * + * @static + * @memberOf _ + * @since 1.2.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + * + * _.unzip(zipped); + * // => [['a', 'b'], [1, 2], [true, false]] + */ + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLikeObject(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); + } + + /** + * This method is like `_.unzip` except that it accepts `iteratee` to specify + * how regrouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @param {Function} [iteratee=_.identity] The function to combine + * regrouped values. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip([1, 2], [10, 20], [100, 200]); + * // => [[1, 10, 100], [2, 20, 200]] + * + * _.unzipWith(zipped, _.add); + * // => [3, 30, 300] + */ + function unzipWith(array, iteratee) { + if (!(array && array.length)) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + return arrayMap(result, function(group) { + return apply(iteratee, undefined, group); + }); + } + + /** + * Creates an array excluding all given values using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.pull`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.xor + * @example + * + * _.without([2, 1, 2, 3], 1, 2); + * // => [3] + */ + var without = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, values) + : []; + }); + + /** + * Creates an array of unique values that is the + * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the given arrays. The order of result values is determined by the order + * they occur in the arrays. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.without + * @example + * + * _.xor([2, 1], [2, 3]); + * // => [1, 3] + */ + var xor = baseRest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); + }); + + /** + * This method is like `_.xor` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2, 3.4] + * + * // The `_.property` iteratee shorthand. + * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var xorBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.xor` except that it accepts `comparator` which is + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.xorWith(objects, others, _.isEqual); + * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var xorWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); + }); + + /** + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the + * second elements of the given arrays, and so on. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + */ + var zip = baseRest(unzip); + + /** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property identifiers and one of corresponding values. + * + * @static + * @memberOf _ + * @since 0.4.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['a', 'b'], [1, 2]); + * // => { 'a': 1, 'b': 2 } + */ + function zipObject(props, values) { + return baseZipObject(props || [], values || [], assignValue); + } + + /** + * This method is like `_.zipObject` except that it supports property paths. + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); + * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } + */ + function zipObjectDeep(props, values) { + return baseZipObject(props || [], values || [], baseSet); + } + + /** + * This method is like `_.zip` except that it accepts `iteratee` to specify + * how grouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @param {Function} [iteratee=_.identity] The function to combine + * grouped values. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { + * return a + b + c; + * }); + * // => [111, 222] + */ + var zipWith = baseRest(function(arrays) { + var length = arrays.length, + iteratee = length > 1 ? arrays[length - 1] : undefined; + + iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; + return unzipWith(arrays, iteratee); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * This method is the wrapper version of `_.at`. + * + * @name at + * @memberOf _ + * @since 1.0.0 + * @category Seq + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _(object).at(['a[0].b.c', 'a[1]']).value(); + * // => [3, 4] + */ + var wrapperAt = flatRest(function(paths) { + var length = paths.length, + start = length ? paths[0] : 0, + value = this.__wrapped__, + interceptor = function(object) { return baseAt(object, paths); }; + + if (length > 1 || this.__actions__.length || + !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ + 'func': thru, + 'args': [interceptor], + 'thisArg': undefined + }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined); + } + return array; + }); + }); + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapped = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapped = wrapped.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapped.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + + /** + * Gets the next value on a wrapped object following the + * [iterator protocol](https://mdn.io/iteration_protocols#iterator). + * + * @name next + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the next iterator value. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped.next(); + * // => { 'done': false, 'value': 1 } + * + * wrapped.next(); + * // => { 'done': false, 'value': 2 } + * + * wrapped.next(); + * // => { 'done': true, 'value': undefined } + */ + function wrapperNext() { + if (this.__values__ === undefined) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, + value = done ? undefined : this.__values__[this.__index__++]; + + return { 'done': done, 'value': value }; + } + + /** + * Enables the wrapper to be iterable. + * + * @name Symbol.iterator + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the wrapper object. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped[Symbol.iterator]() === wrapped; + * // => true + * + * Array.from(wrapped); + * // => [1, 2] + */ + function wrapperToIterator() { + return this; + } + + /** + * Creates a clone of the chain sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @param {*} value The value to plant. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2]).map(square); + * var other = wrapped.plant([3, 4]); + * + * other.value(); + * // => [9, 16] + * + * wrapped.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + clone.__index__ = 0; + clone.__values__ = undefined; + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + + /** + * This method is the wrapper version of `_.reverse`. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + 'func': thru, + 'args': [reverse], + 'thisArg': undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(reverse); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the number of times the key was returned by `iteratee`. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': 1, '6': 2 } + * + * // The `_.property` iteratee shorthand. + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + var countBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } + }); + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + */ + function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ + var findLast = createFind(findLastIndex); + + /** + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMap(collection, iteratee) { + return baseFlatten(map(collection, iteratee), 1); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ + function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); + } + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEach + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `2` then `1`. + */ + function forEachRight(collection, iteratee) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // The `_.property` iteratee shorthand. + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + baseAssignValue(result, key, [value]); + } + }); + + /** + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'a': 1, 'b': 2 }, 1); + * // => true + * + * _.includes('abcd', 'bc'); + * // => true + */ + function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); + } + + /** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array|Function|string} path The path of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + var invokeMap = baseRest(function(collection, path, args) { + var index = -1, + isFunc = typeof path == 'function', + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value) { + result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); + }); + return result; + }); + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var array = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(array, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(array, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + */ + var keyBy = createAggregator(function(result, value, key) { + baseAssignValue(result, key, value); + }); + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.sortBy` except that it allows specifying the sort + * orders of the iteratees to sort by. If `orders` is unspecified, all values + * are sorted in ascending order. Otherwise, specify an order of "desc" for + * descending or "asc" for ascending sort order of corresponding values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] + * The iteratees to sort by. + * @param {string[]} [orders] The sort orders of `iteratees`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 34 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 36 } + * ]; + * + * // Sort by `user` in ascending order and by `age` in descending order. + * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + */ + function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); + } + + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.partition(users, function(o) { return o.active; }); + * // => objects for [['fred'], ['barney', 'pebbles']] + * + * // The `_.matches` iteratee shorthand. + * _.partition(users, { 'age': 1, 'active': false }); + * // => objects for [['pebbles'], ['barney', 'fred']] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.partition(users, ['active', false]); + * // => objects for [['barney', 'pebbles'], ['fred']] + * + * // The `_.property` iteratee shorthand. + * _.partition(users, 'active'); + * // => objects for [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); + } + + /** + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduce + * @example + * + * var array = [[0, 1], [2, 3], [4, 5]]; + * + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); + } + + /** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.filter + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * _.reject(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.reject(users, { 'age': 40, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.reject(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.reject(users, 'active'); + * // => objects for ['barney'] + */ + function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, negate(getIteratee(predicate, 3))); + } + + /** + * Gets a random element from `collection`. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + */ + function sample(collection) { + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); + } + + /** + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @param {number} [n=1] The number of elements to sample. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the random elements. + * @example + * + * _.sampleSize([1, 2, 3], 2); + * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] + */ + function sampleSize(collection, n, guard) { + if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); + } + + /** + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + * @example + * + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] + */ + function shuffle(collection) { + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + return isString(collection) ? stringSize(collection) : collection.length; + } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] + */ + var sortBy = baseRest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees = [iteratees[0]]; + } + return baseOrderBy(collection, baseFlatten(iteratees, 1), []); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ + var now = ctxNow || function() { + return root.Date.now(); + }; + + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it's called `n` or more times. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => Logs 'done saving!' after the two async saves have completed. + */ + function after(n, func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ + function ary(func, n, guard) { + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; + return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); + + /** + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Function + * @param {Object} object The object to invoke the method on. + * @param {string} key The key of the method. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; + * + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; + * + * bound('!'); + * // => 'hiya fred!' + * + * // Bound with placeholders. + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' + */ + var bindKey = baseRest(function(object, key, partials) { + var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); + }); + + /** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ + function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; + } + + /** + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. + * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(3)(1, _)(2); + * // => [1, 2, 3] + */ + function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; + } + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ + function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + result = wait - timeSinceLastCall; + + return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new flipped function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ + function flip(func) { + return createWrap(func, WRAP_FLIP_FLAG); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Expose `MapCache`. + memoize.Cache = MapCache; + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /** + * Creates a function that invokes `func` with its arguments transformed. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms=[_.identity]] + * The argument transforms. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var func = _.overArgs(function(x, y) { + * return [x, y]; + * }, [square, doubled]); + * + * func(9, 3); + * // => [81, 6] + * + * func(10, 5); + * // => [100, 10] + */ + var overArgs = castRest(function(func, transforms) { + transforms = (transforms.length == 1 && isArray(transforms[0])) + ? arrayMap(transforms[0], baseUnary(getIteratee())) + : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); + + var funcsLength = transforms.length; + return baseRest(function(args) { + var index = -1, + length = nativeMin(args.length, funcsLength); + + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); + }); + + /** + * Creates a function that invokes `func` with `partials` prepended to the + * arguments it receives. This method is like `_.bind` except it does **not** + * alter the `this` binding. + * + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 0.2.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' + * + * // Partially applied with placeholders. + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + */ + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders); + }); + + /** + * This method is like `_.partial` except that partially applied arguments + * are appended to the arguments it receives. + * + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + * + * // Partially applied with placeholders. + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' + */ + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders); + }); + + /** + * Creates a function that invokes `func` with arguments arranged according + * to the specified `indexes` where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + * @example + * + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, [2, 0, 1]); + * + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] + */ + var rearg = flatRest(function(func, indexes) { + return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes); + }); + + /** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as + * an array. + * + * **Note:** This method is based on the + * [rest parameter](https://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? start : toInteger(start); + return baseRest(func, start); + } + + /** + * Creates a function that invokes `func` with the `this` binding of the + * create function and an array of arguments much like + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). + * + * **Note:** This method is based on the + * [spread operator](https://mdn.io/spread_operator). + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Function + * @param {Function} func The function to spread arguments over. + * @param {number} [start=0] The start position of the spread. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * say(['fred', 'hello']); + * // => 'fred says hello' + * + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * numbers.then(_.spread(function(x, y) { + * return x + y; + * })); + * // => a Promise of 76 + */ + function spread(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start == null ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { + var array = args[start], + otherArgs = castSlice(args, 0, start); + + if (array) { + arrayPush(otherArgs, array); + } + return apply(func, this, otherArgs); + }); + } + + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } + + /** + * Creates a function that accepts up to one argument, ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.unary(parseInt)); + * // => [6, 8, 10] + */ + function unary(func) { + return ary(func, 1); + } + + /** + * Creates a function that provides `value` to `wrapper` as its first + * argument. Any additional arguments provided to the function are appended + * to those provided to the `wrapper`. The wrapper is invoked with the `this` + * binding of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {*} value The value to wrap. + * @param {Function} [wrapper=identity] The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var p = _.wrap(_.escape, function(func, text) { + * return '

' + func(text) + '

'; + * }); + * + * p('fred, barney, & pebbles'); + * // => '

fred, barney, & pebbles

' + */ + function wrap(value, wrapper) { + return partial(castFunction(wrapper), value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Casts `value` as an array if it's not one. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Lang + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast array. + * @example + * + * _.castArray(1); + * // => [1] + * + * _.castArray({ 'a': 1 }); + * // => [{ 'a': 1 }] + * + * _.castArray('abc'); + * // => ['abc'] + * + * _.castArray(null); + * // => [null] + * + * _.castArray(undefined); + * // => [undefined] + * + * _.castArray(); + * // => [] + * + * var array = [1, 2, 3]; + * console.log(_.castArray(array) === array); + * // => true + */ + function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; + } + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + return baseClone(value, CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined`, + * cloning is handled by the method instead. The `customizer` is invoked with + * up to four arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.cloneWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ + function cloneWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ + function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @see _.cloneWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeepWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ + function cloneDeepWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + var gt = createRelationalOperation(baseGt); + + /** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ + var gte = createRelationalOperation(function(value, other) { + return value >= other; + }); + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as an `ArrayBuffer` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + * @example + * + * _.isArrayBuffer(new ArrayBuffer(2)); + * // => true + * + * _.isArrayBuffer(new Array(2)); + * // => false + */ + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && baseGetTag(value) == boolTag); + } + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + + /** + * Checks if `value` is likely a DOM element. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + * + * _.isElement(''); + * // => false + */ + function isElement(value) { + return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); + } + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * This method is like `_.isEqual` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with up to + * six arguments: (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ + function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; + } + + /** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ + function isError(value) { + if (!isObjectLike(value)) { + return false; + } + var tag = baseGetTag(value); + return tag == errorTag || tag == domExcTag || + (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + + /** + * Checks if `value` is an integer. + * + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ + function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + + /** + * Performs a partial deep comparison between `object` and `source` to + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.isMatch(object, { 'b': 2 }); + * // => true + * + * _.isMatch(object, { 'b': 1 }); + * // => false + */ + function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); + } + + /** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with five + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ + function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ + function isNative(value) { + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); + } + return baseIsNative(value); + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ + function isNil(value) { + return value == null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); + } + + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + function isPlainObject(value) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + + /** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ + function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); + } + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Checks if `value` is classified as a `WeakMap` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. + * @example + * + * _.isWeakMap(new WeakMap); + * // => true + * + * _.isWeakMap(new Map); + * // => false + */ + function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; + } + + /** + * Checks if `value` is classified as a `WeakSet` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. + * @example + * + * _.isWeakSet(new WeakSet); + * // => true + * + * _.isWeakSet(new Set); + * // => false + */ + function isWeakSet(value) { + return isObjectLike(value) && baseGetTag(value) == weakSetTag; + } + + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + * @see _.gt + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + var lt = createRelationalOperation(baseLt); + + /** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to + * `other`, else `false`. + * @see _.gte + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ + var lte = createRelationalOperation(function(value, other) { + return value <= other; + }); + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (symIterator && value[symIterator]) { + return iteratorToArray(value[symIterator]()); + } + var tag = getTag(value), + func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); + + return func(value); + } + + /** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; + } + + /** + * Converts `value` to an integer suitable for use as the length of an + * array-like object. + * + * **Note:** This method is based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toLength(3.2); + * // => 3 + * + * _.toLength(Number.MIN_VALUE); + * // => 0 + * + * _.toLength(Infinity); + * // => 4294967295 + * + * _.toLength('3.2'); + * // => 3 + */ + function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; + } + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); + } + + /** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + + /** + * Converts `value` to a safe integer. A safe integer can be compared and + * represented correctly. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toSafeInteger(3.2); + * // => 3 + * + * _.toSafeInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toSafeInteger(Infinity); + * // => 9007199254740991 + * + * _.toSafeInteger('3.2'); + * // => 3 + */ + function toSafeInteger(value) { + return value + ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) + : (value === 0 ? value : 0); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); + }); + + /** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + + /** + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignInWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); + }); + + /** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Array} Returns the picked values. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + */ + var at = flatRest(baseAt); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties == null ? result : baseAssign(result, properties); + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(args) { + args.push(undefined, customDefaultsAssignIn); + return apply(assignInWith, undefined, args); + }); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ + var defaultsDeep = baseRest(function(args) { + args.push(undefined, customDefaultsMerge); + return apply(mergeWith, undefined, args); + }); + + /** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ + function findKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); + } + + /** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ + function findLastKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); + } + + /** + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forInRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). + */ + function forIn(object, iteratee) { + return object == null + ? object + : baseFor(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forIn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. + */ + function forInRight(object, iteratee) { + return object == null + ? object + : baseForRight(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwnRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forOwn(object, iteratee) { + return object && baseForOwn(object, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. + */ + function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, getIteratee(iteratee, 3)); + } + + /** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functionsIn + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ + function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); + } + + /** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functions + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ + function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasPath(object, path, baseHas); + } + + /** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ + function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); + } + + /** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ + var invert = createInverter(function(result, value, key) { + result[value] = key; + }, constant(identity)); + + /** + * This method is like `_.invert` except that the inverted object is generated + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys + * responsible for generating the inverted value. The iteratee is invoked + * with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Object + * @param {Object} object The object to invert. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invertBy(object); + * // => { '1': ['a', 'c'], '2': ['b'] } + * + * _.invertBy(object, function(value) { + * return 'group' + value; + * }); + * // => { 'group1': ['a', 'c'], 'group2': ['b'] } + */ + var invertBy = createInverter(function(result, value, key) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + }, getIteratee); + + /** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ + var invoke = baseRest(baseInvoke); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + /** + * The opposite of `_.mapValues`; this method creates an object with the + * same values as `object` and keys generated by running each own enumerable + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapValues + * @example + * + * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { + * return key + value; + * }); + * // => { 'a1': 1, 'b2': 2 } + */ + function mapKeys(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, iteratee(value, key, object), value); + }); + return result; + } + + /** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ + function mapValues(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; + } + + /** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + + /** + * This method is like `_.merge` except that it accepts `customizer` which + * is invoked to produce the merged values of the destination and source + * properties. If `customizer` returns `undefined`, merging is handled by the + * method instead. The `customizer` is invoked with six arguments: + * (objValue, srcValue, key, object, source, stack). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} customizer The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * if (_.isArray(objValue)) { + * return objValue.concat(srcValue); + * } + * } + * + * var object = { 'a': [1], 'b': [2] }; + * var other = { 'a': [3], 'b': [4] }; + * + * _.mergeWith(object, other, customizer); + * // => { 'a': [1, 3], 'b': [2, 4] } + */ + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); + }); + + /** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable property paths of `object` that are not omitted. + * + * **Note:** This method is considerably slower than `_.pick`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to omit. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omit(object, ['a', 'c']); + * // => { 'b': '2' } + */ + var omit = flatRest(function(object, paths) { + var result = {}; + if (object == null) { + return result; + } + var isDeep = false; + paths = arrayMap(paths, function(path) { + path = castPath(path, object); + isDeep || (isDeep = path.length > 1); + return path; + }); + copyObject(object, getAllKeysIn(object), result); + if (isDeep) { + result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); + } + var length = paths.length; + while (length--) { + baseUnset(result, paths[length]); + } + return result; + }); + + /** + * The opposite of `_.pickBy`; this method creates an object composed of + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ + function omitBy(object, predicate) { + return pickBy(object, negate(getIteratee(predicate))); + } + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); + }); + + /** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with two arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ + function pickBy(object, predicate) { + if (object == null) { + return {}; + } + var props = arrayMap(getAllKeysIn(object), function(prop) { + return [prop]; + }); + predicate = getIteratee(predicate); + return basePickBy(object, props, function(value, path) { + return predicate(value, path[0]); + }); + } + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + path = castPath(path, object); + + var index = -1, + length = path.length; + + // Ensure the loop is entered when path is empty. + if (!length) { + length = 1; + object = undefined; + } + while (++index < length) { + var value = object == null ? undefined : object[toKey(path[index])]; + if (value === undefined) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; + } + return object; + } + + /** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, ['x', '0', 'y', 'z'], 5); + * console.log(object.x[0].y.z); + * // => 5 + */ + function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); + } + + /** + * This method is like `_.set` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.setWith(object, '[0][1]', 'a', Object); + * // => { '0': { '1': 'a' } } + */ + function setWith(object, path, value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseSet(object, path, value, customizer); + } + + /** + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entries + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ + var toPairs = createToPairs(keys); + + /** + * Creates an array of own and inherited enumerable string keyed-value pairs + * for `object` which can be consumed by `_.fromPairs`. If `object` is a map + * or set, its entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entriesIn + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairsIn(new Foo); + * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) + */ + var toPairsIn = createToPairs(keysIn); + + /** + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable string keyed properties thru `iteratee`, with each invocation + * potentially mutating the `accumulator` object. If `accumulator` is not + * provided, a new object with the same `[[Prototype]]` will be used. The + * iteratee is invoked with four arguments: (accumulator, value, key, object). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @returns {*} Returns the accumulated value. + * @example + * + * _.transform([2, 3, 4], function(result, n) { + * result.push(n *= n); + * return n % 2 == 0; + * }, []); + * // => [4, 9] + * + * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } + */ + function transform(object, iteratee, accumulator) { + var isArr = isArray(object), + isArrLike = isArr || isBuffer(object) || isTypedArray(object); + + iteratee = getIteratee(iteratee, 4); + if (accumulator == null) { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor : []; + } + else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } + else { + accumulator = {}; + } + } + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + + /** + * Removes the property at `path` of `object`. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 7 } }] }; + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + * + * _.unset(object, ['a', '0', 'b', 'c']); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + */ + function unset(object, path) { + return object == null ? true : baseUnset(object, path); + } + + /** + * This method is like `_.set` except that accepts `updater` to produce the + * value to set. Use `_.updateWith` to customize `path` creation. The `updater` + * is invoked with one argument: (value). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.update(object, 'a[0].b.c', function(n) { return n * n; }); + * console.log(object.a[0].b.c); + * // => 9 + * + * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); + * console.log(object.x[0].y.z); + * // => 0 + */ + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + + /** + * This method is like `_.update` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.updateWith(object, '[0][1]', _.constant('a'), Object); + * // => { '0': { '1': 'a' } } + */ + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object == null ? [] : baseValues(object, keys(object)); + } + + /** + * Creates an array of the own and inherited enumerable string keyed property + * values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) + */ + function valuesIn(object) { + return object == null ? [] : baseValues(object, keysIn(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ + function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); + } + + /** + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. + * + * @static + * @memberOf _ + * @since 3.3.0 + * @category Number + * @param {number} number The number to check. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight + * @example + * + * _.inRange(3, 2, 4); + * // => true + * + * _.inRange(4, 8); + * // => true + * + * _.inRange(4, 2); + * // => false + * + * _.inRange(2, 2); + * // => false + * + * _.inRange(1.2, 2); + * // => true + * + * _.inRange(5.2, 4); + * // => false + * + * _.inRange(-3, -2, -6); + * // => true + */ + function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); + } + + /** + * Produces a random number between the inclusive `lower` and `upper` bounds. + * If only one argument is provided a number between `0` and the given number + * is returned. If `floating` is `true`, or either `lower` or `upper` are + * floats, a floating-point number is returned instead of an integer. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Number + * @param {number} [lower=0] The lower bound. + * @param {number} [upper=1] The upper bound. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. + * @example + * + * _.random(0, 5); + * // => an integer between 0 and 5 + * + * _.random(5); + * // => also an integer between 0 and 5 + * + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 + */ + function random(lower, upper, floating) { + if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined; + } + if (floating === undefined) { + if (typeof upper == 'boolean') { + floating = upper; + upper = undefined; + } + else if (typeof lower == 'boolean') { + floating = lower; + lower = undefined; + } + } + if (lower === undefined && upper === undefined) { + lower = 0; + upper = 1; + } + else { + lower = toFinite(lower); + if (upper === undefined) { + upper = lower; + lower = 0; + } else { + upper = toFinite(upper); + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); + } + return baseRandom(lower, upper); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Foo Bar'); + * // => 'fooBar' + * + * _.camelCase('--foo-bar--'); + * // => 'fooBar' + * + * _.camelCase('__FOO_BAR__'); + * // => 'fooBar' + */ + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? capitalize(word) : word); + }); + + /** + * Converts the first character of `string` to upper case and the remaining + * to lower case. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('FRED'); + * // => 'Fred' + */ + function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); + } + + /** + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ + function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); + } + + /** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + + var length = string.length; + position = position === undefined + ? length + : baseClamp(toInteger(position), 0, length); + + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; + } + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ + function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; + } + + /** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__FOO_BAR__'); + * // => 'foo-bar' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Converts `string`, as space separated words, to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.lowerCase('--Foo-Bar--'); + * // => 'foo bar' + * + * _.lowerCase('fooBar'); + * // => 'foo bar' + * + * _.lowerCase('__FOO_BAR__'); + * // => 'foo bar' + */ + var lowerCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toLowerCase(); + }); + + /** + * Converts the first character of `string` to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.lowerFirst('Fred'); + * // => 'fred' + * + * _.lowerFirst('FRED'); + * // => 'fRED' + */ + var lowerFirst = createCaseFirst('toLowerCase'); + + /** + * Pads `string` on the left and right sides if it's shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' + */ + function pad(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + if (!length || strLength >= length) { + return string; + } + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); + } + + /** + * Pads `string` on the right side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padEnd('abc', 6); + * // => 'abc ' + * + * _.padEnd('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padEnd('abc', 3); + * // => 'abc' + */ + function padEnd(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; + } + + /** + * Pads `string` on the left side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padStart('abc', 6); + * // => ' abc' + * + * _.padStart('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padStart('abc', 3); + * // => 'abc' + */ + function padStart(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; + } + + /** + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a + * hexadecimal, in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the + * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category String + * @param {string} string The string to convert. + * @param {number} [radix=10] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {number} Returns the converted integer. + * @example + * + * _.parseInt('08'); + * // => 8 + * + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] + */ + function parseInt(string, radix, guard) { + if (guard || radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); + } + + /** + * Repeats the given string `n` times. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=1] The number of times to repeat the string. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the repeated string. + * @example + * + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' + */ + function repeat(string, n, guard) { + if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + return baseRepeat(toString(string), n); + } + + /** + * Replaces matches for `pattern` in `string` with `replacement`. + * + * **Note:** This method is based on + * [`String#replace`](https://mdn.io/String/replace). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to modify. + * @param {RegExp|string} pattern The pattern to replace. + * @param {Function|string} replacement The match replacement. + * @returns {string} Returns the modified string. + * @example + * + * _.replace('Hi Fred', 'Fred', 'Barney'); + * // => 'Hi Barney' + */ + function replace() { + var args = arguments, + string = toString(args[0]); + + return args.length < 3 ? string : string.replace(args[1], args[2]); + } + + /** + * Converts `string` to + * [snake case](https://en.wikipedia.org/wiki/Snake_case). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. + * @example + * + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + * + * _.snakeCase('--FOO-BAR--'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * Splits `string` by `separator`. + * + * **Note:** This method is based on + * [`String#split`](https://mdn.io/String/split). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to split. + * @param {RegExp|string} separator The separator pattern to split by. + * @param {number} [limit] The length to truncate results to. + * @returns {Array} Returns the string segments. + * @example + * + * _.split('a-b-c', '-', 2); + * // => ['a', 'b'] + */ + function split(string, separator, limit) { + if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { + separator = limit = undefined; + } + limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && ( + typeof separator == 'string' || + (separator != null && !isRegExp(separator)) + )) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); + } + + /** + * Converts `string` to + * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). + * + * @static + * @memberOf _ + * @since 3.1.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. + * @example + * + * _.startCase('--foo-bar--'); + * // => 'Foo Bar' + * + * _.startCase('fooBar'); + * // => 'Foo Bar' + * + * _.startCase('__FOO_BAR__'); + * // => 'FOO BAR' + */ + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + upperFirst(word); + }); + + /** + * Checks if `string` starts with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, + * else `false`. + * @example + * + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true + */ + function startsWith(string, target, position) { + string = toString(string); + position = position == null + ? 0 + : baseClamp(toInteger(position), 0, string.length); + + target = baseToString(target); + return string.slice(position, position + target.length) == target; + } + + /** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is given, it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The template string. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='lodash.templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the compiled template function. + * @example + * + * // Use the "interpolate" delimiter to create a compiled template. + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' + * + * // Use the HTML "escape" delimiter to escape data property values. + * var compiled = _.template('<%- value %>'); + * compiled({ 'value': ' - + + + + + @@ -1259,7 +1428,7 @@ def getCamHtml() { ${devBrdCastHtml} ${clientBl} ${updateAvail} -
+
${camHtml}
@@ -1280,35 +1449,21 @@ def getCamHtml() { -
- - - - - - - - - - - - - -
Video History (Min.)Video History (Max.)
${getRecTimeDesc(state?.minVideoHistoryHours) ?: "Not Available"}${getRecTimeDesc(state?.maxVideoHistoryHours) ?: "Not Available"}
-
+ - - + + +
Nest Aware Public Video Mic Status
${state?.publicShareEnabled.toString()}${state?.audioInputEnabled.toString()}${state?.nestAwareActive == true ? "Active" : "Not Active"}${state?.publicShareEnabled?.toString()}${state?.audioInputEnabled?.toString()}
@@ -1319,14 +1474,14 @@ def getCamHtml() { - FW Version + Firmware Debug Device Type - v${state?.softwareVer.toString()} + v${state?.softwareVer?.toString()} ${state?.debugStatus} - ${state?.devTypeVer.toString()} + ${state?.devTypeVer?.toString()}
@@ -1338,8 +1493,8 @@ def getCamHtml() { - ${state?.lastConnection.toString()} - ${state?.lastUpdatedDt.toString()} + ${state?.lastConnection?.toString()} + ${state?.lastUpdatedDt?.toString()} @@ -1347,16 +1502,17 @@ def getCamHtml() {
-
-

Swipe/Tap to Change Slide

-
+
+ -
- -
+ ${refreshBtnHtml} """ -/* """ */ incHtmlLoadCnt() render contentType: "text/html", data: mainHtml, status: 200 } catch (ex) { - log.error "getCamHtml Exception:", ex - exceptionDataHandler(ex.message, "getCamHtml") + log.error "getCamHtml Exception: ${ex?.message}", ex + exceptionDataHandler(ex?.message, "getCamHtml") + } +} + +def getDeviceTile(devNum) { + try { + def updateAvail = !state.updateAvailable ? "" : """
Device Update Available!
""" + def clientBl = state?.clientBl ? """
Your Manager client has been blacklisted!\nPlease contact the NST Manager developer to get the issue resolved!!!
""" : "" + def pubVidUrl = state?.public_share_url + def camHtml = (pubVidUrl && state?.camUUID && state?.isStreaming && state?.isOnline) ? showCamHtml(true) : hideCamHtml() + def mainHtml = """ + ${clientBl} + ${updateAvail} + ${getCamIframHtml()} +
+
+
+ ${camHtml} +
+
+

Device Info

+ + + + + + + + + + ${state?.onlineStatus} + ${state?.apiStatus} + + +
Network StatusAPI Status
+
+
+ + + + + + + + + + + + + + + + +
Nest AwarePublic VideoMic Status
${state?.nestAwareActive == true ? "Active" : "Not Active"}${state?.publicShareEnabled?.toString()}${state?.audioInputEnabled?.toString()}
+
+
+ + + + + + + + + + + + + + +
FW VersionDebugDevice Type
v${state?.softwareVer?.toString()}${state?.debugStatus}${state?.devTypeVer?.toString()}
+
+
+ + + + + + + + + + + +
Last Online ChangeData Last Received
${state?.lastConnection?.toString()}${state?.lastUpdatedDt?.toString()}
+
+
+
+
+

Swipe/Drag to Change Slide

+
+
+
+
+ + """ + return mainHtml + } + catch (ex) { + log.error "getDeviceTile Exception: ${ex?.message}", ex + exceptionDataHandler(ex?.message, "getDeviceTile") } } -def showCamHtml() { +def showCamHtml(tile=false) { def pubVidUrl = state?.public_share_url if(!state?.camUUID) { getCamUUID(getPublicVidID()) } def camUUID = state?.camUUID @@ -1413,8 +1706,8 @@ def showCamHtml() { def camImgUrl = "${apiServer}/get_image?uuid=${camUUID}&width=410" def camPlaylistUrl = "https://${liveStreamURL}/nexus_aac/${camUUID}/playlist.m3u8" - def animationUrl = state?.animation_url ? getFileBase64(state?.animation_url, 'image', 'gif') : null - def pubSnapUrl = state?.snapshot_url ? getFileBase64(state?.snapshot_url, 'image', 'jpeg') : null + def animationUrl = state?.animation_url ?: null + def pubSnapUrl = state?.snapshot_url ?: null def vidBtn = (!state?.isStreaming || !liveStreamURL) ? "" : """Live Video""" def imgBtn = (!state?.isStreaming || !pubSnapUrl) ? "" : """Still Image""" @@ -1423,10 +1716,10 @@ def showCamHtml() { def data = """
${androidDisclaimerMsg()} -
-
+
+

Last Camera Event

- +
@@ -1438,8 +1731,8 @@ def showCamHtml() {
-
- +
+
@@ -1457,9 +1750,9 @@ def showCamHtml() {
-
+

Still Image

-
+
""" : "" + def schedData = state?.curAutoSchedData + def schedHtml = "" + if(schedData) { + schedHtml = """ +
+

Automation Schedule

+
diff --git a/devicetypes/tonesto7/nest-presence.src/nest-presence.groovy b/devicetypes/tonesto7/nest-presence.src/nest-presence.groovy index 0f5faaf96..7742e0bc0 100644 --- a/devicetypes/tonesto7/nest-presence.src/nest-presence.groovy +++ b/devicetypes/tonesto7/nest-presence.src/nest-presence.groovy @@ -3,7 +3,7 @@ * Author: Anthony S. (@tonesto7) * Co-Authors: Ben W. (@desertBlade), Eric S. (@E_Sch) * - * Copyright (C) 2017 Anthony S., Ben W. + * Copyright (C) 2017, 2018, 2019 Anthony S., Ben W. * Licensing Info: Located at https://raw.githubusercontent.com/tonesto7/nest-manager/master/LICENSE.md */ @@ -11,7 +11,7 @@ import java.text.SimpleDateFormat preferences { } -def devVer() { return "5.2.0" } +def devVer() { return "5.4.4" } // for the UI metadata { @@ -57,19 +57,20 @@ metadata { state("default", label: 'Data Last Received:\n${currentValue}') } valueTile("apiStatus", "device.apiStatus", width: 2, height: 1, decoration: "flat", wordWrap: true) { - state "ok", label: "API Status:\nOK" - state "issue", label: "API Status:\nISSUE ", backgroundColor: "#FFFF33" + state "Good", label: "API Status:\nOK" + state "Sporadic", label: "API Status:\nISSUE ", backgroundColor: "#FFFF33" + state "Outage", label: "API Status:\nISSUE ", backgroundColor: "#FFFF33" } standardTile("refresh", "device.refresh", width:2, height:2, decoration: "flat") { state "default", action:"refresh.refresh", icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/refresh_icon.png" } valueTile("devTypeVer", "device.devTypeVer", width: 2, height: 1, decoration: "flat") { - state("default", label: 'Device Type:\nv${currentValue}') + state("default", label: 'Device Type:\nv${currentValue}', defaultState: true) } - htmlTile(name:"html", action: "getHtml", width: 6, height: 4, whitelist: ["raw.githubusercontent.com", "cdn.rawgit.com"]) + // htmlTile(name:"html", action: "getHtml", width: 6, height: 4, whitelist: ["raw.githubusercontent.com", "cdn.rawgit.com"]) main ("presence") - details ("presence", "nestPresence", "refresh", "html") + details ("presence", "nestPresence", "lastUpdateDt", "apiStatus", "devTypeVer", "refresh") } } @@ -79,8 +80,7 @@ mappings { void installed() { Logger("installed...") - initialize() - state?.isInstalled = true + runIn(5, "initialize", [overwrite: true]) } def initialize() { @@ -89,6 +89,7 @@ def initialize() { if (!state.updatedLastRanAt || now() >= state.updatedLastRanAt + 2000) { state.updatedLastRanAt = now() verifyHC() + state?.isInstalled = true } else { log.trace "initialize(): Ran within last 2 seconds - SKIPPING" } @@ -96,7 +97,7 @@ def initialize() { void updated() { Logger("updated...") - initialize() + runIn(5, "initialize", [overwrite: true]) } def useTrackedHealth() { return state?.useTrackedHealth ?: false } @@ -130,9 +131,7 @@ def modifyDeviceStatus(status) { def ping() { Logger("ping...") -// if(useTrackedHealth()) { - keepAwakeEvent() -// } + keepAwakeEvent() } def keepAwakeEvent() { @@ -193,20 +192,19 @@ def processEvent(data) { def eventData = data?.evt state.remove("eventData") //log.trace("processEvent Parsing data ${eventData}") - try { +// try { LogAction("------------START OF API RESULTS DATA------------", "warn") if(eventData) { state.isBeta = eventData?.isBeta == true ? true : false state.hcRepairEnabled = eventData?.hcRepairEnabled == true ? true : false state.showLogNamePrefix = eventData?.logPrefix == true ? true : false state.enRemDiagLogging = eventData?.enRemDiagLogging == true ? true : false - state.healthMsg = eventData?.healthNotify == true ? true : false -// if(useTrackedHealth()) { - if(eventData.hcTimeout && (state?.hcTimeout != eventData?.hcTimeout || !state?.hcTimeout)) { - state.hcTimeout = eventData?.hcTimeout - verifyHC() - } -// } + state.healthMsg = eventData?.healthNotify?.healthMsg == true ? true : false + state.healthMsgWait = eventData?.healthNotify?.healthMsgWait + if(eventData.hcTimeout && (state?.hcTimeout != eventData?.hcTimeout || !state?.hcTimeout)) { + state.hcTimeout = eventData?.hcTimeout + verifyHC() + } state.nestTimeZone = eventData?.tz ?: null state.clientBl = eventData?.clientBl == true ? true : false state.mobileClientType = eventData?.mobileClientType @@ -215,11 +213,11 @@ def processEvent(data) { presenceEvent(eventData?.pres) apiStatusEvent((!eventData?.apiIssues ? false : true)) deviceVerEvent(eventData?.latestVer.toString()) - if(eventData?.allowDbException) { state?.allowDbException = eventData?.allowDbException = false ? false : true } + if(eventData?.allowDbException) { state?.allowDbException = eventData?.allowDbException == false ? false : true } lastUpdatedEvent(true) - if(eventData?.lastStrucDataUpd) { - def newDt = formatDt(Date.parse("E MMM dd HH:mm:ss z yyyy", eventData?.lastStrucDataUpd?.toString())) + if(eventData?.lastStrDataUpd) { + def newDt = formatDt(Date.parse("E MMM dd HH:mm:ss z yyyy", eventData?.lastStrDataUpd?.toString())) //log.debug "newDt: $newDt" def curDt = Date.parse("E MMM dd HH:mm:ss z yyyy", getDtNow()) def lastDt = Date.parse("E MMM dd HH:mm:ss z yyyy", newDt?.toString()) @@ -234,17 +232,20 @@ def processEvent(data) { //This will return all of the devices state data to the logs. //log.debug "Device State Data: ${getState()}" return null - } +/* } catch (ex) { log.error "generateEvent Exception:", ex - exceptionDataHandler(ex.message, "generateEvent") + exceptionDataHandler(ex?.message, "generateEvent") } +*/ } def getDataByName(String name) { state[name] ?: device.getDataValue(name) } +def getDevTypeId() { return device?.getTypeId() } + def getDeviceStateData() { return getState() } @@ -337,8 +338,7 @@ def presenceEvent(presence) { def apiStatusEvent(issue) { def curStat = device.currentState("apiStatus")?.value - def newStat = issue ? "issue" : "ok" - state?.apiStatus = newStat + def newStat = issue if(isStateChange(device, "apiStatus", newStat.toString())) { Logger("UPDATED | API Status is: (${newStat}) | Original State: (${curStat})") sendEvent(name: "apiStatus", value: newStat, descriptionText: "API Status is: ${newStat}", displayed: true, isStateChange: true, state: newStat) @@ -363,7 +363,8 @@ def healthNotifyOk() { def lastDt = state?.lastHealthNotifyDt if(lastDt) { def ldtSec = getTimeDiffSeconds(lastDt) - if(ldtSec < 600) { + def t0 = state?.healthMsgWait ?: 3600 + if(ldtSec < t0) { return false } } @@ -393,7 +394,7 @@ void setPresence() { } catch (ex) { log.error "setPresence Exception:", ex - exceptionDataHandler(ex.message, "setPresence") + exceptionDataHandler(ex?.message, "setPresence") } } @@ -405,7 +406,7 @@ void setAway() { } catch (ex) { log.error "setAway Exception:", ex - exceptionDataHandler(ex.message, "setAway") + exceptionDataHandler(ex?.message, "setAway") } } @@ -417,7 +418,7 @@ void setHome() { } catch (ex) { log.error "setHome Exception:", ex - exceptionDataHandler(ex.message, "setHome") + exceptionDataHandler(ex?.message, "setHome") } } @@ -425,29 +426,30 @@ void setHome() { | LOGGING FUNCTIONS | *************************************************************************************************/ void Logger(msg, logType = "debug") { - def smsg = state?.showLogNamePrefix ? "${device.displayName}: ${msg}" : "${msg}" - switch (logType) { - case "trace": - log.trace "${smsg}" - break - case "debug": - log.debug "${smsg}" - break - case "info": - log.info "${smsg}" - break - case "warn": - log.warn "${smsg}" - break - case "error": - log.error "${smsg}" - break - default: - log.debug "${smsg}" - break - } + def smsg = state?.showLogNamePrefix ? "${device.displayName} (v${devVer()}) | ${msg}" : "${msg}" if(state?.enRemDiagLogging) { parent.saveLogtoRemDiagStore(smsg, logType, "Presence") + } else { + switch (logType) { + case "trace": + log.trace "${smsg}" + break + case "debug": + log.debug "${smsg}" + break + case "info": + log.info "${smsg}" + break + case "warn": + log.warn "${smsg}" + break + case "error": + log.error "${smsg}" + break + default: + log.debug "${smsg}" + break + } } } @@ -499,7 +501,6 @@ def getTimeDiffSeconds(strtDate, stpDate=null, methName=null) { //LogTrace("[GetTimeDiffSeconds] StartDate: $strtDate | StopDate: ${stpDate ?: "Not Sent"} | MethodName: ${methName ?: "Not Sent"})") try { if(strtDate) { - //if(strtDate?.contains("dtNow")) { return 10000 } def now = new Date() def stopVal = stpDate ? stpDate.toString() : getDtNow() def startDt = Date.parse("E MMM dd HH:mm:ss z yyyy", strtDate) @@ -515,42 +516,26 @@ def getTimeDiffSeconds(strtDate, stpDate=null, methName=null) { } } -def getFileBase64(url,preType,fileType) { - def params = [ - uri: url, - contentType: '$preType/$fileType' - ] +def getFileBase64(url, preType, fileType) { + def params = [uri: url, contentType: "$preType/$fileType"] httpGet(params) { resp -> - if(resp.data) { - def respData = resp?.data - ByteArrayOutputStream bos = new ByteArrayOutputStream() - int len - int size = 4096 - byte[] buf = new byte[size] - while ((len = respData.read(buf, 0, size)) != -1) - bos.write(buf, 0, len) - buf = bos.toByteArray() - //log.debug "buf: $buf" - String s = buf?.encodeBase64() - //log.debug "resp: ${s}" - return s ? "data:${preType}/${fileType};base64,${s.toString()}" : null + if(resp?.status == 200) { + if(resp.data) { + def respData = resp?.data + byte[] byteData = resp?.data?.getBytes() + String enc = byteData?.encodeBase64() + // log.debug "enc: ${enc}" + return enc ? "data:${preType}/${fileType};base64,${enc?.toString()}" : null + } + } else { + LogAction("getFileBase64 Resp: ${resp?.status} ${url}", "error") + exceptionDataHandler("resp ${ex?.response?.status} ${url}", "getFileBase64") + return null } } } -def getCssData() { - def cssData = null - def htmlInfo = state?.htmlInfo - if(htmlInfo?.cssUrl && htmlInfo?.cssVer) { - cssData = getFileBase64(htmlInfo.cssUrl, "text", "css") - state?.cssVer = htmlInfo?.cssVer - } else { - cssData = getFileBase64(cssUrl(), "text", "css") - } - return cssData -} - -def cssUrl() { return "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Documents/css/ST-HTML.min.css" } +def hasHtml() { return false } def getHtml() { try { @@ -568,7 +553,7 @@ def getHtml() { - + ${clientBl} @@ -581,10 +566,10 @@ def getHtml() { } catch (ex) { log.error "getHtml Exception:", ex - exceptionDataHandler(ex.message, "getHtml") + exceptionDataHandler(ex?.message, "getHtml") } } -private def textDevName() { return "Nest Presence${appDevName()}" } -private def appDevType() { return false } -private def appDevName() { return appDevType() ? " (Dev)" : "" } +private def textDevName() { return "Nest Presence${appDevName()}" } +private def appDevType() { return false } +private def appDevName() { return appDevType() ? " (Dev)" : "" } diff --git a/devicetypes/tonesto7/nest-protect.src/nest-protect.groovy b/devicetypes/tonesto7/nest-protect.src/nest-protect.groovy index fabb92b73..363e34a53 100644 --- a/devicetypes/tonesto7/nest-protect.src/nest-protect.groovy +++ b/devicetypes/tonesto7/nest-protect.src/nest-protect.groovy @@ -3,7 +3,7 @@ * Author: Anthony S. (@tonesto7) * Co-Authors: Ben W. (@desertblade), Eric S. (@E_Sch) * - * Copyright (C) 2017 Anthony S. + * Copyright (C) 2017, 2018, 2019 Anthony S. * Licensing Info: Located at https://raw.githubusercontent.com/tonesto7/nest-manager/master/LICENSE.md */ @@ -11,10 +11,10 @@ import java.text.SimpleDateFormat preferences { } -def devVer() { return "5.2.0" } +def devVer() { return "5.4.3" } metadata { - definition (name: "${textDevName()}", author: "Anthony S.", namespace: "tonesto7") { + definition (name: "${textDevName()}", author: "Anthony S.", namespace: "tonesto7", ocfDeviceType: "x.com.st.d.sensor.smoke", vid: "generic-smoke-co") { //capability "Polling" capability "Actuator" capability "Sensor" @@ -110,7 +110,7 @@ metadata { valueTile("uiColor", "device.uiColor", inactiveLabel: false, width: 2, height: 1, decoration: "flat", wordWrap: true) { state("default", label: 'UI Color:\n${currentValue}') } - valueTile("softwareVer", "device.softwareVer", inactiveLabel: false, width: 2, height: 1, decoration: "flat", wordWrap: true) { + valueTile("softwareVer", "device.softwareVer", inactiveLabel: false, width: 3, height: 1, decoration: "flat", wordWrap: true) { state("default", label: 'Firmware:\nv${currentValue}') } valueTile("lastConnection", "device.lastConnection", inactiveLabel: false, width: 3, height: 1, decoration: "flat", wordWrap: true) { @@ -122,24 +122,29 @@ metadata { standardTile("refresh", "device.refresh", width:2, height:2, decoration: "flat") { state "default", action:"refresh.refresh", icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/refresh_icon.png" } - valueTile("lastUpdatedDt", "device.lastUpdatedDt", width: 4, height: 1, decoration: "flat", wordWrap: true) { + valueTile("lastUpdatedDt", "device.lastUpdatedDt", width: 3, height: 1, decoration: "flat", wordWrap: true) { state("default", label: 'Data Last Received:\n${currentValue}') } - valueTile("devTypeVer", "device.devTypeVer", width: 2, height: 1, decoration: "flat") { - state("default", label: 'Device Type:\nv${currentValue}') + valueTile("devTypeVer", "device.devTypeVer", width: 3, height: 1, decoration: "flat") { + state("default", label: 'Device Type:\nv${currentValue}', defaultState: true) } valueTile("apiStatus", "device.apiStatus", width: 2, height: 1, decoration: "flat", wordWrap: true) { - state "ok", label: "API Status:\nOK" - state "issue", label: "API Status:\nISSUE ", backgroundColor: "#FFFF33" + state "Good", label: "API Status:\nOK" + state "Sporadic", label: "API Status:\nISSUE ", backgroundColor: "#FFFF33" + state "Outage", label: "API Status:\nISSUE ", backgroundColor: "#FFFF33" } valueTile("debugOn", "device.debugOn", width: 2, height: 1, decoration: "flat") { state "true", label: 'Debug:\n${currentValue}' state "false", label: 'Debug:\n${currentValue}' } + valueTile("remind", "device.blah", inactiveLabel: false, width: 6, height: 2, decoration: "flat", wordWrap: true) { + state("default", label: 'Reminder:\nHTML Content is Available in SmartApp', defaultState: true) + } htmlTile(name:"devInfoHtml", action: "getInfoHtml", width: 6, height: 8) main "main2" - details(["alarmState", "devInfoHtml", "refresh"]) + // details(["alarmState", "devInfoHtml","remind", "refresh"]) + details(["alarmState", "smoke", "batteryState", "carbonMonoxide", "onlineStatus","debugOn", "apiStatus", "lastConnection", "lastUpdatedDt", "lastTested","devTypeVer", "softwareVer","remind", "refresh"]) } } @@ -153,7 +158,7 @@ def initialize() { if (!state.updatedLastRanAt || now() >= state.updatedLastRanAt + 2000) { state.updatedLastRanAt = now() verifyHC() - //poll() + state?.isInstalled = true } else { log.trace "initialize(): Ran within last 2 seconds - SKIPPING" } @@ -161,13 +166,12 @@ def initialize() { void installed() { Logger("installed...") - initialize() - state?.isInstalled = true + runIn(5, "initialize", [overwrite: true]) } void updated() { Logger("updated...") - initialize() + runIn(5, "initialize", [overwrite: true]) } def useTrackedHealth() { return state?.useTrackedHealth ?: false } @@ -175,7 +179,7 @@ def useTrackedHealth() { return state?.useTrackedHealth ?: false } def getHcTimeout() { def toBatt = state?.hcBattTimeout def toWire = state?.hcWireTimeout - return ((device.currentValue("powerSourceNest") == "wired") ? (toWire instanceof Integer ? toWire : 35) : (toBatt instanceof Integer ? toBatt : 1500))*60 + return ((device.currentValue("powerSourceNest") == "wired") ? (toWire instanceof Integer ? toWire : 45) : (toBatt instanceof Integer ? toBatt : 1500))*60 } void verifyHC() { @@ -201,10 +205,8 @@ def modifyDeviceStatus(status) { } def ping() { -// if(useTrackedHealth()) { - Logger("ping...") - keepAwakeEvent() -// } + Logger("ping...") + keepAwakeEvent() } def keepAwakeEvent() { @@ -254,7 +256,7 @@ void runSmokeTest() { schedEndTest() } catch (ex) { log.error "runSmokeTest Exception:", ex - exceptionDataHandler(ex.message, "runSmokeTest") + exceptionDataHandler(ex?.message, "runSmokeTest") } } @@ -267,7 +269,7 @@ void runCoTest() { schedEndTest() } catch (ex) { log.error "runCoTest Exception:", ex - exceptionDataHandler(ex.message, "runCoTest") + exceptionDataHandler(ex?.message, "runCoTest") } } @@ -280,7 +282,7 @@ void runBatteryTest() { schedEndTest() } catch (ex) { log.error "runBatteryTest Exception:", ex - exceptionDataHandler(ex.message, "runBatteryTest") + exceptionDataHandler(ex?.message, "runBatteryTest") } } @@ -290,7 +292,7 @@ void schedEndTest() { refresh() // this typically takes more than 5 seconds to complete } catch (ex) { log.error "schedEndTest Exception:", ex - exceptionDataHandler(ex.message, "schedEndTest") + exceptionDataHandler(ex?.message, "schedEndTest") } } @@ -302,7 +304,7 @@ void endTest() { refresh() } catch (ex) { log.error "endTest Exception:", ex - exceptionDataHandler(ex.message, "endTest") + exceptionDataHandler(ex?.message, "endTest") } } @@ -326,7 +328,7 @@ def processEvent(data) { state.remove("eventData") //log.trace("processEvent Parsing data ${eventData}") - try { +// try { LogAction("------------START OF API RESULTS DATA------------", "warn") if(eventData) { def results = eventData?.data @@ -335,14 +337,13 @@ def processEvent(data) { state.restStreaming = eventData?.restStreaming == true ? true : false state.showLogNamePrefix = eventData?.logPrefix == true ? true : false state.enRemDiagLogging = eventData?.enRemDiagLogging == true ? true : false - state.healthMsg = eventData?.healthNotify == true ? true : false -// if(useTrackedHealth()) { - if((eventData.hcBattTimeout && (state?.hcBattTimeout != eventData?.hcBattTimeout || !state?.hcBattTimeout)) || (eventData.hcWireTimeout && (state?.hcWireTimeout != eventData?.hcWireTimeout || !state?.hcWireTimeout))) { - state.hcBattTimeout = eventData?.hcBattTimeout - state.hcWireTimeout = eventData?.hcWireTimeout - verifyHC() - } -// } + state.healthMsg = eventData?.healthNotify?.healthMsg == true ? true : false + state.healthMsgWait = eventData?.healthNotify?.healthMsgWait + if((eventData.hcBattTimeout && (state?.hcBattTimeout != eventData?.hcBattTimeout || !state?.hcBattTimeout)) || (eventData.hcWireTimeout && (state?.hcWireTimeout != eventData?.hcWireTimeout || !state?.hcWireTimeout))) { + state.hcBattTimeout = eventData?.hcBattTimeout + state.hcWireTimeout = eventData?.hcWireTimeout + verifyHC() + } state?.useMilitaryTime = eventData?.mt ? true : false state.clientBl = eventData?.clientBl == true ? true : false state.mobileClientType = eventData?.mobileClientType @@ -361,19 +362,19 @@ def processEvent(data) { softwareVerEvent(results?.software_version.toString()) deviceVerEvent(eventData?.latestVer.toString()) state?.devBannerData = eventData?.devBannerData ?: null - if(eventData?.htmlInfo) { state?.htmlInfo = eventData?.htmlInfo } - if(eventData?.allowDbException) { state?.allowDbException = eventData?.allowDbException = false ? false : true } + if(eventData?.allowDbException) { state?.allowDbException = eventData?.allowDbException == false ? false : true } determinePwrSrc() - lastUpdatedEvent() + lastUpdatedEvent(true) checkHealth() } return null - } +/* } catch (ex) { log.error "generateEvent Exception:", ex - exceptionDataHandler(ex.message, "generateEvent") + exceptionDataHandler(ex?.message, "generateEvent") } +*/ } def getDtNow() { @@ -410,6 +411,7 @@ def getTimeDiffSeconds(strtDate, stpDate=null, methName=null) { def getStateSize() { return state?.toString().length() } def getStateSizePerc() { return (int) ((stateSize/100000)*100).toDouble().round(0) } +def getDevTypeId() { return device?.getTypeId() } def getDataByName(String name) { state[name] ?: device.getDataValue(name) @@ -472,8 +474,6 @@ def lastCheckinEvent(checkin, isOnline) { tf.setTimeZone(getTimeZone()) def lastChk = device.currentState("lastConnection")?.value - def lastConnSeconds = lastChk ? getTimeDiffSeconds(lastChk) : 9000 // try not to disrupt running average for pwr determination - def prevOnlineStat = device.currentState("onlineStatus")?.value def hcTimeout = getHcTimeout() @@ -482,11 +482,6 @@ def lastCheckinEvent(checkin, isOnline) { def curConnSeconds = (checkin && curConnFmt != "Not Available") ? getTimeDiffSeconds(curConnFmt) : 3000 def onlineStat = isOnline.toString() == "true" ? "online" : "offline" - LogAction("lastCheckinEvent($checkin, $isOnline) | onlineStatus: $onlineStat | lastConnSeconds: $lastConnSeconds | hcTimeout: ${hcTimeout} | curConnSeconds: ${curConnSeconds}") - if(hcTimeout && isOnline.toString() == "true" && curConnSeconds > hcTimeout && lastConnSeconds > hcTimeout) { - onlineStat = "offline" - LogAction("lastCheckinEvent: UPDATED onlineStatus: $onlineStat") - } state?.lastConnection = curConn?.toString() if(isStateChange(device, "lastConnection", curConnFmt.toString())) { @@ -495,6 +490,17 @@ def lastCheckinEvent(checkin, isOnline) { if(lastConnSeconds >= 0 && onlineStat == "online") { addCheckinTime(lastConnSeconds) } } else { LogAction("Last Nest Check-in was: (${curConnFmt}) | Original State: (${lastChk})") } + lastChk = device.currentState("lastConnection")?.value + def lastConnSeconds = lastChk ? getTimeDiffSeconds(lastChk) : 9000 // try not to disrupt running average for pwr determination + + if(hcTimeout && isOnline.toString() == "true" && curConnSeconds > hcTimeout && lastConnSeconds > hcTimeout) { + onlineStat = "offline" + LogAction("lastCheckinEvent: UPDATED onlineStatus: $onlineStat") + Logger("lastCheckinEvent($checkin, $isOnline) | onlineStatus: $onlineStat | lastConnSeconds: $lastConnSeconds | hcTimeout: ${hcTimeout} | curConnSeconds: ${curConnSeconds}") + } else { + LogAction("lastCheckinEvent($checkin, $isOnline) | onlineStatus: $onlineStat | lastConnSeconds: $lastConnSeconds | hcTimeout: ${hcTimeout} | curConnSeconds: ${curConnSeconds}") + } + state?.onlineStatus = onlineStat modifyDeviceStatus(onlineStat) if(isStateChange(device, "onlineStatus", onlineStat.toString())) { @@ -526,16 +532,16 @@ def addCheckinTime(val) { def determinePwrSrc() { if(!state?.checkinTimeList) { state?.checkinTimeList = [] } def checkins = state?.checkinTimeList - def checkinAvg = checkins?.size() ? (checkins?.sum()/checkins?.size()).toDouble().round(0).toInteger() : null // + def checkinAvg = checkins?.size() ? ( checkins?.sum()?.div(checkins?.size()))?.toDouble()?.round(0).toInteger() : null if(checkins?.size() > 7) { if(checkinAvg && checkinAvg < 10000) { powerTypeEvent(true) - } else { powerTypeEvent(false) } + } else { powerTypeEvent() } } //log.debug "checkins: $checkins | Avg: $checkinAvg" } -def powerTypeEvent(wired) { +def powerTypeEvent(wired=false) { def curVal = device.currentState("powerSourceNest")?.value def newValSt = wired == true ? "wired" : "battery" def newVal = wired == true ? "mains" : "battery" @@ -583,7 +589,7 @@ def debugOnEvent(debug) { def apiStatusEvent(issue) { def curStat = device.currentState("apiStatus")?.value - def newStat = issue ? "Has Issue" : "Good" + def newStat = issue state?.apiStatus = newStat if(isStateChange(device, "apiStatus", newStat.toString())) { Logger("UPDATED | API Status is: (${newStat.toString().capitalize()}) | Original State: (${curStat.toString().capitalize()})") @@ -680,7 +686,8 @@ def healthNotifyOk() { def lastDt = state?.lastHealthNotifyDt if(lastDt) { def ldtSec = getTimeDiffSeconds(lastDt) - if(ldtSec < 600) { + def t0 = state?.healthMsgWait ?: 3600 + if(ldtSec < t0) { return false } } @@ -705,30 +712,31 @@ def lastN(String input, n) { } void Logger(msg, logType = "debug") { - def smsg = state?.showLogNamePrefix ? "${device.displayName}: ${msg}" : "${msg}" - switch (logType) { - case "trace": - log.trace "${smsg}" - break - case "debug": - log.debug "${smsg}" - break - case "info": - log.info "${smsg}" - break - case "warn": - log.warn "${smsg}" - break - case "error": - log.error "${smsg}" - break - default: - log.debug "${smsg}" - break - } + def smsg = state?.showLogNamePrefix ? "${device.displayName} (v${devVer()}) | ${msg}" : "${msg}" def theId = lastN(device.getId().toString(),5) if(state?.enRemDiagLogging) { parent.saveLogtoRemDiagStore(smsg, logType, "Protect-${theId}") + } else { + switch (logType) { + case "trace": + log.trace "${smsg}" + break + case "debug": + log.debug "${smsg}" + break + case "info": + log.info "${smsg}" + break + case "warn": + log.warn "${smsg}" + break + case "error": + log.error "${smsg}" + break + default: + log.debug "${smsg}" + break + } } } @@ -759,48 +767,48 @@ def getMetricCntData() { return [protHtmlLoadCnt:(state?.htmlLoadCnt ?: 0)]//, protInfoBtnTapCnt:(state?.infoBtnTapCnt ?: 0)] } -def getCarbonImg() { +def getCarbonImg(b64=true) { def carbonVal = device.currentState("nestCarbonMonoxide")?.value //values in ST are tested, clear, detected //values from nest are ok, warning, emergency def img = "" - def caption = "${carbonVal?.toString().toUpperCase()}" + def caption = "${carbonVal ? carbonVal?.toString().toUpperCase() : ""}" def captionClass = "" switch(carbonVal) { case "warning": - img = getFileBase64(getImg("co2_warn_status.png"), "image", "png") + img = getImg("co2_warn_status.png") captionClass = "alarmWarnCap" break case "emergency": - img = getFileBase64(getImg("co2_emergency_status.png"), "image", "png") + img = getImg("co2_emergency_status.png") captionClass = "alarmEmerCap" break default: - img = getFileBase64(getImg("co2_clear_status.png"), "image", "png") + img = getImg("co2_clear_status.png") captionClass = "alarmClearCap" break } return ["img":img, "caption": caption, "captionClass":captionClass] } -def getSmokeImg() { +def getSmokeImg(b64=true) { def smokeVal = device.currentState("nestSmoke")?.value //values in ST are tested, clear, detected //values from nest are ok, warning, emergency def img = "" - def caption = "${smokeVal?.toString().toUpperCase()}" + def caption = "${smokeVal ? smokeVal?.toString().toUpperCase() : ""}" def captionClass = "" switch(smokeVal) { case "warning": - img = getFileBase64(getImg("smoke_warn_status.png"), "image", "png") + img = getImg("smoke_warn_status.png") captionClass = "alarmWarnCap" break case "emergency": - img = getFileBase64(getImg("smoke_emergency_status.png"), "image", "png") + img = getImg("smoke_emergency_status.png") captionClass = "alarmEmerCap" break default: - img = getFileBase64(getImg("smoke_clear_status.png"), "image", "png") + img = getImg("smoke_clear_status.png") captionClass = "alarmClearCap" break } @@ -843,47 +851,28 @@ def devVerInfo() { return getWebData([uri: "https://raw.githubusercontent.com/${ def getFileBase64(url, preType, fileType) { try { - def params = [ - uri: url, - contentType: '$preType/$fileType' - ] + def params = [uri: url, contentType: "$preType/$fileType"] httpGet(params) { resp -> - if(resp.data) { - def respData = resp?.data - ByteArrayOutputStream bos = new ByteArrayOutputStream() - int len - int size = 4096 - byte[] buf = new byte[size] - while ((len = respData.read(buf, 0, size)) != -1) - bos.write(buf, 0, len) - buf = bos.toByteArray() - //log.debug "buf: $buf" - String s = buf?.encodeBase64() - //log.debug "resp: ${s}" - return s ? "data:${preType}/${fileType};base64,${s.toString()}" : null + if(resp?.status == 200) { + if(resp.data) { + def respData = resp?.data + byte[] byteData = resp?.data?.getBytes() + String enc = byteData?.encodeBase64() + // log.debug "enc: ${enc}" + return enc ? "data:${preType}/${fileType};base64,${enc?.toString()}" : null + } + } else { + LogAction("getFileBase64 Resp: ${resp?.status} ${url}", "error") + exceptionDataHandler("resp ${ex?.response?.status} ${url}", "getFileBase64") + return null } } - } - catch (ex) { + } catch (ex) { log.error "getFileBase64 Exception:", ex - exceptionDataHandler(ex.message, "getFileBase64") - } -} - -def getCssData() { - def cssData = null - def htmlInfo = state?.htmlInfo - if(htmlInfo?.cssUrl && htmlInfo?.cssVer) { - cssData = getFileBase64(htmlInfo.cssUrl, "text", "css") - state?.cssVer = htmlInfo?.cssVer - } else { - cssData = getFileBase64(cssUrl(), "text", "css") + exceptionDataHandler(ex?.message, "getFileBase64") } - return cssData } -def cssUrl() { return "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Documents/css/ST-HTML.min.css" } - def disclaimerMsg() { if(!state?.disclaimerMsgShown) { state.disclaimerMsgShown = true @@ -903,7 +892,7 @@ def getChgLogHtml() { if(!state?.shownChgLog == true) { chgStr = """ - + - - - - + + + + ${getChgLogHtml()} @@ -1072,10 +1060,114 @@ def getInfoHtml() { } catch (ex) { log.error "getInfoHtml Exception:", ex - exceptionDataHandler(ex.message, "getInfoHtml") + exceptionDataHandler(ex?.message, "getInfoHtml") } } +def getDeviceTile(devNum) { + try { + def battImg = (state?.battVal == "replace") ? """""" : """""" + + def testVal = device.currentState("isTesting")?.value + def testModeHTML = (testVal.toString() == "true") ? "

Test Mode

" : "" + def updateAvail = !state.updateAvailable ? "" : """
Device Update Available!
""" + def clientBl = state?.clientBl ? """
Your Manager client has been blacklisted!\nPlease contact the Nest Manager developer to get the issue resolved!!!
""" : "" + + def smokeImg = getSmokeImg(false) + def carbonImg = getCarbonImg(false) + def html = """ + ${testModeHTML} + ${clientBl} + ${updateAvail} +
+
+

Alarm Status

+ + + + + + + + + + + + + +
Smoke DetectorCarbon Monoxide
+ + ${smokeImg?.caption} + + + ${carbonImg?.caption} +
+
+
+
+

Device Info

+ + + + + + + + + + + + ${state?.onlineStatus.toString().capitalize()} + + ${state?.apiStatus} + + +
Network StatusPower TypeAPI Status
${state?.powerSource != null ? state?.powerSource.toString().capitalize() : "Not Available Yet"}
+
+
+ + + + + + + + + + + + + + + + +
Firmware VersionDebugDevice Type
v${state?.softwareVer.toString()}${state?.debugStatus}${state?.devTypeVer.toString()}
+
+
+ + + + + + + + + + + +
Last Check-InData Last Received
${state?.lastConnection.toString()}${state?.lastUpdatedDt.toString()}
+
+
+ """ + return html + } + catch (ex) { + log.error "getDeviceTile Exception:", ex + exceptionDataHandler(ex?.message, "getInfoHtml") + } +} + + private def textDevName() { return "Nest Protect${appDevName()}" } private def appDevType() { return false } private def appDevName() { return appDevType() ? " (Dev)" : "" } diff --git a/devicetypes/tonesto7/nest-thermostat.src/nest-thermostat.groovy b/devicetypes/tonesto7/nest-thermostat.src/nest-thermostat.groovy index c98183edb..9f1391b6e 100644 --- a/devicetypes/tonesto7/nest-thermostat.src/nest-thermostat.groovy +++ b/devicetypes/tonesto7/nest-thermostat.src/nest-thermostat.groovy @@ -6,29 +6,23 @@ * Graphing Modeled on code from Andreas Amann (@ahndee) * * Modeled after the EcoBee thermostat under Templates in the IDE - * Copyright (C) 2017 Anthony S. + * Copyright (C) 2017, 2018, 2019 Anthony S. * Licensing Info: Located at https://raw.githubusercontent.com/tonesto7/nest-manager/master/LICENSE.md */ import java.text.SimpleDateFormat import groovy.time.* -def devVer() { return "5.2.0" } +def devVer() { return "5.4.6" } // for the UI metadata { - definition (name: "${textDevName()}", namespace: "tonesto7", author: "Anthony S.") { + definition (name: "${textDevName()}", namespace: "tonesto7", author: "Anthony S.", vid: "SmartThings-smartthings-Z-Wave_Thermostat", ocfDeviceType: "oic.d.thermostat") { capability "Actuator" capability "Relative Humidity Measurement" capability "Refresh" capability "Sensor" capability "Thermostat" - capability "Thermostat Cooling Setpoint" - capability "Thermostat Fan Mode" - capability "Thermostat Heating Setpoint" - capability "Thermostat Mode" - capability "Thermostat Operating State" - capability "Thermostat Setpoint" capability "Temperature Measurement" capability "Health Check" @@ -60,7 +54,10 @@ metadata { command "updateNestReportData" command "ecoDesc", ["string"] command "whoMadeChanges", ["string", "string", "string"] + command "setNestEta", ["string", "string", "string"] + command "cancelNestEta", ["string"] + attribute "etaBegin", "string" attribute "devVer", "string" attribute "temperatureUnit", "string" attribute "targetTemp", "string" @@ -95,6 +92,7 @@ metadata { attribute "sunlightCorrectionActive", "string" attribute "timeToTarget", "string" attribute "nestType", "string" + attribute "usingEmergencyHeat", "string" attribute "pauseUpdates", "string" attribute "nestReportData", "string" attribute "previousthermostatMode", "string" @@ -102,6 +100,7 @@ metadata { attribute "whoMadeChangesDesc", "string" attribute "whoMadeChangesDescDt", "string" attribute "whoSetEcoMode", "string" + attribute "temperatureur", "string" } simulator { @@ -111,20 +110,20 @@ metadata { tiles(scale: 2) { multiAttributeTile(name:"temperature", type:"thermostat", width:6, height:4, canChangeIcon: true) { tileAttribute("device.temperature", key: "PRIMARY_CONTROL") { - attributeState("default", label:'${currentValue}°') + attributeState("temperature", label:'${currentValue}\u00b0') } tileAttribute("device.temperature", key: "VALUE_CONTROL") { - attributeState("default", action: "levelUpDown") + // attributeState("default", action: "levelUpDown") attributeState("VALUE_UP", action: "levelUp") attributeState("VALUE_DOWN", action: "levelDown") } tileAttribute("device.humidity", key: "SECONDARY_CONTROL") { - attributeState("default", label:'${currentValue}%', unit:"%") + attributeState("humidity", label:'${currentValue}%', unit:"%", defaultState: true) } tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE") { attributeState("idle", backgroundColor:"#44B621") - attributeState("heating", backgroundColor:"#FFA81E") - attributeState("cooling", backgroundColor:"#2ABBF0") + attributeState("heating", backgroundColor:"#e86d13") + attributeState("cooling", backgroundColor:"#00a0dc") attributeState("fan only", backgroundColor:"#145D78") attributeState("pending heat", backgroundColor:"#B27515") attributeState("pending cool", backgroundColor:"#197090") @@ -146,50 +145,49 @@ metadata { } } valueTile("temp2", "device.temperature", width: 2, height: 2, decoration: "flat") { - state("default", label:'${currentValue}°', icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/nest_like.png", + state("default", label:'${currentValue}\u00b0', icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/nest_like.png", backgroundColors: getTempColors()) } - standardTile("thermostatMode", "device.nestThermostatMode", width:2, height:2, decoration: "flat") { - state("off", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/off_btn_icon.png") - state("heat", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_btn_icon.png") - state("cool", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/cool_btn_icon.png") - state("auto", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_cool_btn_icon.png") - state("eco", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/eco_icon.png") + standardTile("thermostatMode", "device.nestThermostatMode", width: 2, height: 2, supportedStates: "device.supportedThermostatModes", decoration: "flat") { + state("off", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/off_btn_icon.png") + state("heat", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_btn_icon.png") + state("cool", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/cool_btn_icon.png") + state("auto", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_cool_btn_icon.png") + state("eco", action:"changeMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/eco_icon.png") state("emergency heat", action:"changeMode", nextState: "updating", icon: "st.thermostat.emergency") state("updating", label:"", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/cmd_working.png") } - - standardTile("offBtn", "device.off", width:1, height:1, decoration: "flat") { + standardTile("offBtn", "device.off", width:2, height:2, decoration: "flat") { state("default", action: "offbtn", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/off_btn_icon.png") } - standardTile("ecoBtn", "device.eco", width:1, height:1, decoration: "flat") { + standardTile("ecoBtn", "device.eco", width:2, height:2, decoration: "flat") { state("default", action: "ecobtn", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/eco_icon.png") } - standardTile("heatBtn", "device.canHeat", width:1, height:1, decoration: "flat") { + standardTile("heatBtn", "device.canHeat", width:2, height:2, decoration: "flat") { state("true", action: "heatbtn", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_btn_icon.png") state "false", label: '' } - standardTile("coolBtn", "device.canCool", width:1, height:1, decoration: "flat") { + standardTile("coolBtn", "device.canCool", width:2, height:2, decoration: "flat") { state("true", action: "coolbtn", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/cool_btn_icon.png") state "false", label: '' } - standardTile("autoBtn", "device.hasAuto", width:1, height:1, decoration: "flat") { + standardTile("autoBtn", "device.hasAuto", width:2, height:2, decoration: "flat") { state("true", action: "autobtn", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_cool_btn_icon.png") state "false", label: '' } standardTile("thermostatFanMode", "device.thermostatFanMode", width:2, height:2, decoration: "flat") { - state("auto", action: "changeFanMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/fan_auto_icon.png") - state("on", action: "changeFanMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/fan_on_icon.png") + state("auto", action: "changeFanMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/fan_auto_icon.png") + state("on", action: "changeFanMode", nextState: "updating", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/fan_on_icon.png") state("updating", label:"", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/cmd_working.png") state "disabled", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/fan_disabled_icon.png" } standardTile("nestPresence", "device.nestPresence", width:2, height:2, decoration: "flat") { - state "home", action: "setPresence", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/pres_home_icon.png" - state "away", action: "setPresence", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/pres_away_icon.png" - state "auto-away", action: "setPresence", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/pres_autoaway_icon.png" - state "unknown", action: "setPresence", icon: "st.unknown.unknown.unknown" + state "home", action: "setPresence", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/pres_home_icon.png" + state "away", action: "setPresence", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/pres_away_icon.png" + state "auto-away", action: "setPresence", icon: "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/pres_autoaway_icon.png" + state "unknown", action: "setPresence", icon: "st.unknown.unknown.unknown" } standardTile("refresh", "device.refresh", width:2, height:2, decoration: "flat") { state "default", action:"refresh.refresh", icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/refresh_icon.png" @@ -224,20 +222,51 @@ metadata { state "default", label:'', action:"coolingSetpointDown", icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/cool_arrow_down.png" state "", label: '' } - controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 3, range: getRange(), inactiveLabel: false) { + controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 3, range: getRange(), debouncePeriod: 1500, inactiveLabel: false) { state "setCoolingSetpoint", action:"setCoolingSetpoint", backgroundColor:"#0099FF" state "", label: '' } - + valueTile("softwareVer", "device.softwareVer", inactiveLabel: false, width: 3, height: 1, decoration: "flat", wordWrap: true) { + state("default", label: 'Firmware:\nv${currentValue}') + } + valueTile("lastConnection", "device.lastConnection", inactiveLabel: false, width: 3, height: 1, decoration: "flat", wordWrap: true) { + state("default", label: 'Tstat Last Checked-In:\n${currentValue}') + } + valueTile("lastUpdatedDt", "device.lastUpdatedDt", width: 3, height: 1, decoration: "flat", wordWrap: true) { + state("default", label: 'Data Last Received:\n${currentValue}') + } + valueTile("devTypeVer", "device.devTypeVer", width: 3, height: 1, decoration: "flat") { + state("default", label: 'Device Type:\nv${currentValue}', defaultState: true) + } + valueTile("apiStatus", "device.apiStatus", width: 2, height: 1, decoration: "flat", wordWrap: true) { + state "Good", label: "API Status:\nOK" + state "Sporadic", label: "API Status:\nISSUE ", backgroundColor: "#FFFF33" + state "Outage", label: "API Status:\nISSUE ", backgroundColor: "#FFFF33" + } + valueTile("debugOn", "device.debugOn", width: 2, height: 1, decoration: "flat") { + state "true", label: 'Debug:\n${currentValue}' + state "false", label: 'Debug:\n${currentValue}' + } + valueTile("onlineStatus", "device.onlineStatus", width: 2, height: 1, wordWrap: true, decoration: "flat") { + state("default", label: 'Network Status:\n${currentValue}') + } standardTile("blank", "device.heatingSetpoint", width: 1, height: 1, canChangeIcon: false, decoration: "flat") { state "default", label: '' } + standardTile("blank2", "device.heatingSetpoint", width: 2, height: 2, canChangeIcon: false, decoration: "flat") { + state "default", label: '' + } htmlTile(name:"graphHTML", action: "graphHTML", width: 6, height: 13, whitelist: ["www.gstatic.com", "raw.githubusercontent.com", "cdn.rawgit.com"]) - + valueTile("remind", "device.blah", inactiveLabel: false, width: 6, height: 2, decoration: "flat", wordWrap: true) { + state("default", label: 'Reminder:\nHTML Graph and History Content is Available in SmartApp', defaultState: true) + } main("temp2") - details( ["temperature", "thermostatMode", "nestPresence", "thermostatFanMode", - "heatingSetpointDown", "heatingSetpoint", "heatingSetpointUp", "coolingSetpointDown", "coolingSetpoint", "coolingSetpointUp", - "heatSliderControl", "coolSliderControl", "graphHTML", "offBtn", "ecoBtn", "heatBtn", "coolBtn", "autoBtn", "blank", "refresh"] ) + details([ + "temperature", "thermostatMode", "nestPresence", "thermostatFanMode", + "heatingSetpointDown", "heatingSetpoint", "heatingSetpointUp", "coolingSetpointDown", "coolingSetpoint", "coolingSetpointUp", + "heatSliderControl", "coolSliderControl", "autoBtn", "heatBtn", "coolBtn", "offBtn", "ecoBtn", "blank2", "onlineStatus","debugOn", + "apiStatus", "lastConnection", "lastUpdatedDt", "devTypeVer", "softwareVer", "graphHTML", "remind", "refresh" + ]) } preferences { input "resetHistoryOnly", "bool", title: "Reset History Data", description: "", displayDuringSetup: false @@ -246,36 +275,30 @@ metadata { } def compileForC() { - def retVal = false // if using C mode, set this to true so that enums and colors are correct (due to ST issue of compile time evaluation) - return retVal + // if using C mode, set this to true so that enums and colors are correct (due to ST issue of compile time evaluation) + return false } def getTempColors() { def colorMap -//getTemperatureScale() == "C" wantMetric() - if(compileForC()) { colorMap = [ // Celsius Color Range [value: 0, color: "#153591"], [value: 7, color: "#1e9cbb"], [value: 15, color: "#90d2a7"], [value: 23, color: "#44b621"], - [value: 29, color: "#f1d801"], - [value: 33, color: "#d04e00"], - [value: 36, color: "#bc2323"] - ] - } else { - colorMap = [ + [value: 28, color: "#f1d801"], + [value: 35, color: "#d04e00"], + [value: 37, color: "#bc2323"], // Fahrenheit Color Range [value: 40, color: "#153591"], [value: 44, color: "#1e9cbb"], [value: 59, color: "#90d2a7"], [value: 74, color: "#44b621"], [value: 84, color: "#f1d801"], - [value: 92, color: "#d04e00"], + [value: 95, color: "#d04e00"], [value: 96, color: "#bc2323"] ] - } } def lowRange() { return compileForC() ? 9 : 50 } @@ -302,10 +325,19 @@ void checkStateClear() { Logger("checkStateClear...resetting ALL toggle") state.resetAllData = false } + if(before > 65) { + Logger("checkStateClear...Clearing HISTORY ${before}") + def data = getState()?.findAll { + (it?.key in ["today", "temperatureTable", "operatingStateTable", "humidityTable", "coolSetpointTable", "heatSetpointTable", "extTempTable", "fanModeTable", "historyStoreMap", "temperatureTableYesterday", "operatingStateTableYesterday", "humidityTableYesterday", "coolSetpointTableYesterday", "heatSetpointTableYesterday", "extTempTableYesterday", "fanModeTableYesterday" ]) + } + data.each { item -> + state.remove(item?.key.toString()) + } + } if(!state?.resetHistoryOnly && resetHistoryOnly) { Logger("checkStateClear...Clearing HISTORY") def data = getState()?.findAll { - (it?.key in ["today", "temperatureTable", "operatingStateTable", "humidityTable", "historyStoreMap", "temperatureTableYesterday", "operatingStateTableYesterday", "humidityTableYesterday"]) + (it?.key in ["today", "temperatureTable", "operatingStateTable", "humidityTable", "coolSetpointTable", "heatSetpointTable", "extTempTable", "fanModeTable", "historyStoreMap", "temperatureTableYesterday", "operatingStateTableYesterday", "humidityTableYesterday", "coolSetpointTableYesterday", "heatSetpointTableYesterday", "extTempTableYesterday", "fanModeTableYesterday" ]) } data.each { item -> state.remove(item?.key.toString()) @@ -326,6 +358,7 @@ def initialize() { state.updatedLastRanAt = now() checkVirtualStatus() verifyHC() + state.isInstalled = true } else { log.trace "initialize(): Ran within last 2 seconds - SKIPPING" } @@ -333,13 +366,14 @@ def initialize() { void installed() { Logger("installed...") - initialize() - state.isInstalled = true + runIn( 5, "initialize", [overwrite: true] ) } void updated() { Logger("Device Updated...") - initialize() + //setNestEta("EricTst", "2018-01-27T01:02:00.000Z", "2018-01-27T02:15:00.000Z") + //cancelNestEta("EricTst") + runIn( 5, "initialize", [overwrite: true] ) } void checkVirtualStatus() { @@ -360,7 +394,7 @@ def useTrackedHealth() { return state?.useTrackedHealth ?: false } def getHcTimeout() { def to = state?.hcTimeout - return ((to instanceof Integer) ? to.toInteger() : 35)*60 + return ((to instanceof Integer) ? to.toInteger() : 45)*60 } void verifyHC() { @@ -387,9 +421,7 @@ def modifyDeviceStatus(status) { def ping() { Logger("ping...") -// if(useTrackedHealth()) { - keepAwakeEvent() -// } + keepAwakeEvent() } def keepAwakeEvent() { @@ -448,7 +480,7 @@ void processEvent(data) { checkStateClear() //LogAction("processEvent Parsing data ${eventData}", "trace") - try { +// try { LogAction("------------START OF API RESULTS DATA------------", "warn") if(eventData) { state.isBeta = eventData?.isBeta == true ? true : false @@ -457,18 +489,17 @@ void processEvent(data) { state.useMilitaryTime = eventData?.mt ? true : false state.showLogNamePrefix = eventData?.logPrefix == true ? true : false state.enRemDiagLogging = eventData?.enRemDiagLogging == true ? true : false - state.healthMsg = eventData?.healthNotify == true ? true : false + state.healthMsg = eventData?.healthNotify?.healthMsg == true ? true : false + state.healthMsgWait = eventData?.healthNotify?.healthMsgWait state.showGraphs = eventData?.showGraphs != null ? eventData?.showGraphs : true - if(eventData?.allowDbException) { state?.allowDbException = eventData?.allowDbException = false ? false : true } + if(eventData?.allowDbException) { state?.allowDbException = eventData?.allowDbException == false ? false : true } debugOnEvent(eventData?.debug ? true : false) deviceVerEvent(eventData?.latestVer.toString()) if(virtType()) { nestTypeEvent("virtual") } else { nestTypeEvent("physical") } -// if(useTrackedHealth()) { - if(eventData.hcTimeout && (state?.hcTimeout != eventData?.hcTimeout || !state?.hcTimeout)) { - state.hcTimeout = eventData?.hcTimeout - verifyHC() - } -// } + if(eventData.hcTimeout && (state?.hcTimeout != eventData?.hcTimeout || !state?.hcTimeout)) { + state.hcTimeout = eventData?.hcTimeout + verifyHC() + } if(state?.swVersion != devVer()) { initialize() state.swVersion = devVer() @@ -485,6 +516,7 @@ void processEvent(data) { canHeatCool(eventData?.data?.can_heat, eventData?.data?.can_cool) hasFan(eventData?.data?.has_fan.toString()) presenceEvent(eventData?.pres) + etaEvent(eventData?.etaBegin) def curMode = device?.currentState("nestThermostatMode")?.stringValue hvacModeEvent(eventData?.data?.hvac_mode.toString()) @@ -507,10 +539,10 @@ void processEvent(data) { softwareVerEvent(eventData?.data?.software_version.toString()) //onlineStatusEvent(eventData?.data?.is_online.toString()) apiStatusEvent(eventData?.apiIssues) - if(eventData?.htmlInfo) { state?.htmlInfo = eventData?.htmlInfo } safetyTempsEvent(eventData?.safetyTemps) comfortHumidityEvent(eventData?.comfortHumidity) comfortDewpointEvent(eventData?.comfortDewpoint) + emergencyHeatEvent(eventData?.data?.is_using_emergency_heat) state.voiceReportPrefs = eventData?.vReportPrefs autoSchedDataEvent(eventData?.autoSchedData) state?.devBannerData = eventData?.devBannerData ?: null @@ -618,21 +650,23 @@ void processEvent(data) { break } getSomeData(true) - lastUpdatedEvent() + lastUpdatedEvent(true) checkHealth() } //This will return all of the devices state data to the logs. //LogAction("Device State Data: ${getState()}") return null +/* } catch (ex) { log.error "generateEvent Exception:", ex - exceptionDataHandler(ex.message, "generateEvent") + exceptionDataHandler(ex?.message, "generateEvent") } +*/ } def getStateSize() { return state?.toString().length() } -def getStateSizePerc() { return (int) ((stateSize/100000)*100).toDouble().round(0) } // +def getStateSizePerc() { return (int) ((stateSize/100000)*100).toDouble().round(0) } def getDataByName(String name) { state[name] ?: device.getDataValue(name) @@ -651,7 +685,7 @@ def getTimeZone() { } def tUnitStr() { - return "°${state?.tempUnit}" + return "\u00b0${state?.tempUnit}" } def isCodeUpdateAvailable(newVer, curVer) { @@ -774,13 +808,11 @@ def lastCheckinEvent(checkin, isOnline) { tf.setTimeZone(getTimeZone()) def lastChk = device.currentState("lastConnection")?.value - def lastConnSeconds = (lastChk && lastChk != "Not Available") ? getTimeDiffSeconds(lastChk) : 3000 - def prevOnlineStat = device.currentState("onlineStatus")?.value def hcTimeout = getHcTimeout() - def curConn = checkin ? "${tf.format(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", checkin))}" : "Not Available" - def curConnFmt = checkin ? "${formatDt(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", checkin))}" : "Not Available" + def curConn = checkin ? tf.format(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", checkin)) : "Not Available" + def curConnFmt = checkin ? formatDt(Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", checkin)) : "Not Available" def curConnSeconds = (checkin && curConnFmt != "Not Available") ? getTimeDiffSeconds(curConnFmt) : 3000 def onlineStat = isOnline.toString() == "true" ? "online" : "offline" @@ -791,11 +823,15 @@ def lastCheckinEvent(checkin, isOnline) { sendEvent(name: 'lastConnection', value: curConnFmt?.toString(), isStateChange: true) } else { LogAction("Last Nest Check-in was: (${curConnFmt}) | Original State: (${lastChk})") } - LogAction("lastCheckinEvent($checkin, $isOnline) | onlineStatus: $onlineStat | lastConnSeconds: $lastConnSeconds | hcTimeout: ${hcTimeout} | curConnSeconds: ${curConnSeconds}") + lastChk = device.currentState("lastConnection")?.value + def lastConnSeconds = (lastChk && lastChk != "Not Available") ? getTimeDiffSeconds(lastChk) : 3000 if(hcTimeout && isOnline.toString() == "true" && curConnSeconds > hcTimeout && lastConnSeconds > hcTimeout) { onlineStat = "offline" LogAction("lastCheckinEvent: UPDATED onlineStatus: $onlineStat") + Logger("lastCheckinEvent($checkin, $isOnline) | onlineStatus: $onlineStat | lastConnSeconds: $lastConnSeconds | hcTimeout: ${hcTimeout} | curConnSeconds: ${curConnSeconds}") + } else { + LogAction("lastCheckinEvent($checkin, $isOnline) | onlineStatus: $onlineStat | lastConnSeconds: $lastConnSeconds | hcTimeout: ${hcTimeout} | curConnSeconds: ${curConnSeconds}") } state?.onlineStatus = onlineStat @@ -808,7 +844,7 @@ def lastCheckinEvent(checkin, isOnline) { def lastUpdatedEvent(sendEvt=false) { def now = new Date() - def formatVal = state.useMilitaryTime ? "MMM d, yyyy - HH:mm:ss" : "MMM d, yyyy - h:mm:ss a" + def formatVal = state?.useMilitaryTime ? "MMM d, yyyy - HH:mm:ss" : "MMM d, yyyy - h:mm:ss a" def tf = new SimpleDateFormat(formatVal) tf.setTimeZone(getTimeZone()) def lastDt = "${tf?.format(now)}" @@ -878,10 +914,14 @@ def thermostatSetpointEvent(Double targetTemp) { def temperatureEvent(Double tempVal) { def temp = device.currentState("temperature")?.stringValue def rTempVal = wantMetric() ? tempVal.round(1) : tempVal.round(0).toInteger() + def unrounded_rTempVal = tempVal.round(1) if(isStateChange(device, "temperature", rTempVal.toString())) { LogAction("UPDATED | Temperature is (${rTempVal}${tUnitStr()}) | Original Temp: (${temp}${tUnitStr()})") sendEvent(name:'temperature', value: rTempVal, unit: state?.tempUnit, descriptionText: "Ambient Temperature is ${rTempVal}${tUnitStr()}", displayed: true, isStateChange: true) } else { LogAction("Temperature is (${rTempVal}${tUnitStr()}) | Original Temp: (${temp})${tUnitStr()}") } + if(isStateChange(device, "temperatureur", unrounded_rTempVal.toString())) { + sendEvent(name:'temperatureur', value: unrounded_rTempVal, unit: state?.tempUnit, descriptionText: "Ambient Temperature is ${rTempVal}${tUnitStr()}", displayed: false, isStateChange: true) + } checkSafetyTemps() } @@ -971,6 +1011,16 @@ def humidityEvent(humidity) { } else { LogAction("Humidity is (${humidity}) | Original State: (${hum})") } } +def etaEvent(eta) { + if(eta) { + def oeta = device.currentState("etaBegin")?.value + if(isStateChange(device, "etaBegin", eta.toString())) { + LogAction("UPDATED | Eta Begin is (${eta}) | Original State: (${oeta})") + sendEvent(name:'etaBegin', value: eta, descriptionText: "Eta is ${eta}", displayed: true, isStateChange: true) + } else { LogAction("Eta Begin is (${eta}) | Original State: (${oeta})") } + } +} + def presenceEvent(String presence) { // log.trace "presenceEvent($presence)" def val = getPresence() @@ -1013,7 +1063,8 @@ void whoMadeChanges(autoType, desc, dt) { def ecoDescEvent(val, updChk=false) { //log.debug "ecoDescEvent($val)" def curMode = device?.currentState("nestThermostatMode")?.stringValue - def curEcoDesc = device?.currentState("whoSetEcoMode")?.value ?: null + def t0 = device?.currentState("whoSetEcoMode")?.value + def curEcoDesc = t0 ?: null def newVal = updChk ? curEcoDesc : val def newEcoDesc = (curMode == "eco") ? (newVal == null ? "Set Outside of this DTH" : newVal) : "Not in Eco Mode" @@ -1032,15 +1083,17 @@ def ecoDescEvent(val, updChk=false) { def hvacModeEvent(mode) { def hvacMode = !state?.hvac_mode ? device.currentState("thermostatMode")?.stringValue : state.hvac_mode def newMode = (mode == "heat-cool") ? "auto" : mode +/* if(mode == "eco") { if(state?.can_cool && state?.can_heat) { newMode = "auto" } else if(state?.can_heat) { newMode = "heat" } else if(state?.can_cool) { newMode = "cool" } } +*/ state?.hvac_mode = newMode if(!hvacMode.equals(newMode)) { Logger("UPDATED | Hvac Mode is (${newMode.toString().capitalize()}) | Original State: (${hvacMode.toString().capitalize()})") - sendEvent(name: "thermostatMode", value: newMode, descriptionText: "HVAC mode is ${newMode} mode", displayed: true, isStateChange: true) + sendEvent(name: "thermostatMode", value: newMode, data:[supportedThermostatModes: device.currentValue("supportedThermostatModes")], descriptionText: "HVAC mode is ${newMode} mode", displayed: true, isStateChange: true) } def oldnestmode = state?.nestHvac_mode @@ -1208,7 +1261,7 @@ def onlineStatusEvent(online) { def apiStatusEvent(issue) { def curStat = device.currentState("apiStatus")?.value - def newStat = issue ? "Has Issue" : "Good" + def newStat = issue state?.apiStatus = newStat if(isStateChange(device, "apiStatus", newStat.toString())) { Logger("UPDATED | API Status is: (${newStat.toString().capitalize()}) | Original State: (${curStat.toString().capitalize()})") @@ -1235,8 +1288,18 @@ def autoSchedDataEvent(schedData) { state?.curAutoSchedData = schedData } +def emergencyHeatEvent(emerHeat) { + def curStat = device.currentState("usingEmergencyHeat")?.value + def newStat = emerHeat + if(isStateChange(device, "usingEmergencyHeat", newStat.toString())) { + state.is_using_emergency_heat = !!newStat + Logger("Using Emergency Heat is: (${newStat.toString().capitalize()}) | Previous State: (${curStat.toString().capitalize()})") + sendEvent(name: "usingEmergencyHeat", value: newStat, descriptionText: "Using Emergency Heat is: ${newStat}", displayed: true, isStateChange: true, state: newStat) + } +} + def canHeatCool(canHeat, canCool) { - def supportedThermostatModes = ["off"] + def supportedThermostatModes = ["off", "eco"] state?.can_heat = !canHeat ? false : true if(state.can_heat) { supportedThermostatModes << "heat" } state?.can_cool = !canCool ? false : true @@ -1258,7 +1321,7 @@ def canHeatCool(canHeat, canCool) { } def nestSupportedThermostatModes = supportedThermostatModes.collect() - nestSupportedThermostatModes << "eco" + //nestSupportedThermostatModes << "eco" if(state?.supportedNestThermostatModes != nestSupportedThermostatModes) { sendEvent(name: "supportedNestThermostatModes", value: nestSupportedThermostatModes) state.supportedNestThermostatModes = nestSupportedThermostatModes.collect() @@ -1348,9 +1411,11 @@ def getTempWaitVal() { def wantMetric() { return (state?.tempUnit == "C") } -def getHealthStatus(lower=false) { +def getDevTypeId() { return device?.getTypeId() } + +def getHealthStatus(lowerCase=false) { def res = device?.getStatus() - if(lower) { return res.toString().toLowerCase() } + if(lowerCase) { return res.toString().toLowerCase() } return res.toString() } @@ -1358,7 +1423,8 @@ def healthNotifyOk() { def lastDt = state?.lastHealthNotifyDt if(lastDt) { def ldtSec = getTimeDiffSeconds(lastDt) - if(ldtSec < 600) { + def t0 = state.healthMsgWait ?: 3600 + if(ldtSec < t0) { return false } } @@ -1576,7 +1642,7 @@ def GetTimeDiffSeconds(lastDate) { def lastDt = Date.parse("E MMM dd HH:mm:ss z yyyy", lastDate) def start = Date.parse("E MMM dd HH:mm:ss z yyyy", formatDt(lastDt)).getTime() def stop = Date.parse("E MMM dd HH:mm:ss z yyyy", formatDt(now)).getTime() - def diff = (int) (long) (stop - start) / 1000 // + def diff = (int) (long) (stop - start) / 1000 return diff } @@ -1590,7 +1656,7 @@ def getTimeDiffSeconds(strtDate, stpDate=null, methName=null) { def stopDt = Date.parse("E MMM dd HH:mm:ss z yyyy", stopVal) def start = Date.parse("E MMM dd HH:mm:ss z yyyy", formatDt(startDt)).getTime() def stop = Date.parse("E MMM dd HH:mm:ss z yyyy", stopVal).getTime() - def diff = (int) (long) (stop - start) / 1000 // + def diff = (int) (long) (stop - start) / 1000 //LogTrace("[GetTimeDiffSeconds] Results for '$methName': ($diff seconds)") return diff } else { return null } @@ -1686,11 +1752,14 @@ void changeSetpoint() { // Nest Only allows F temperatures as #.0 and C temperatures as either #.0 or #.5 void setHeatingSetpoint(temp, manChg=false) { - setHeatingSetpoint(temp.toDouble(), manChg) + if(temp != null) { + setHeatingSetpoint(temp.toDouble(), manChg) + } } void setHeatingSetpoint(Double reqtemp, manChg=false) { LogAction("setHeatingSetpoint()... ($reqtemp)", "trace") + if(reqtemp == null) { return } def hvacMode = getHvacMode() def tempUnit = state?.tempUnit def temp = 0.0 @@ -1708,7 +1777,7 @@ void setHeatingSetpoint(Double reqtemp, manChg=false) { if(canHeat && state?.nestHvac_mode != "eco") { switch (tempUnit) { case "C": - temp = Math.round(reqtemp.round(1) * 2) / 2.0f // + temp = Math.round(reqtemp.round(1) * 2) / 2.0f if(curMinTemp < 9.0) { curMinTemp = 9.0 } if(curMaxTemp > 32.0) { curMaxTemp = 32.0 } if(temp) { @@ -1761,11 +1830,14 @@ void setHeatingSetpoint(Double reqtemp, manChg=false) { } void setCoolingSetpoint(temp, manChg=false) { - setCoolingSetpoint( temp.toDouble(), manChg) + if(temp != null) { + setCoolingSetpoint( temp.toDouble(), manChg) + } } void setCoolingSetpoint(Double reqtemp, manChg=false) { LogAction("setCoolingSetpoint()... ($reqtemp)", "trace") + if(reqtemp == null) { return } def hvacMode = getHvacMode() def temp = 0.0 def tempUnit = state?.tempUnit @@ -1783,7 +1855,7 @@ void setCoolingSetpoint(Double reqtemp, manChg=false) { if(canCool && state?.nestHvac_mode != "eco") { switch (tempUnit) { case "C": - temp = Math.round(reqtemp.round(1) * 2) / 2.0f // + temp = Math.round(reqtemp.round(1) * 2) / 2.0f if(curMinTemp < 9.0) { curMinTemp = 9.0 } if(curMaxTemp > 32.0) { curMaxTemp = 32.0 } if(temp) { @@ -1873,6 +1945,16 @@ def setHome() { if(parent.setStructureAway(this, "false", virtType()) ) { presenceEvent("home") } } +def setNestEta(tripId, begin, end){ + LogAction("setNestEta()...", "trace") + parent?.setEtaState(this, ["trip_id": "${tripId}", "estimated_arrival_window_begin": "${begin}", "estimated_arrival_window_end": "${end}" ], virtType() ) +} + +def cancelNestEta(tripId){ + LogAction("cancelNestEta()...", "trace") + parent?.cancelEtaState(this, "${tripId}", virtType() ) +} + /************************************************************************************************ | HVAC MODE FUNCTIONS | ************************************************************************************************/ @@ -2065,7 +2147,7 @@ void fanOn() { } catch (ex) { log.error "fanOn Exception:", ex - exceptionDataHandler(ex.message, "fanOn") + exceptionDataHandler(ex?.message, "fanOn") } } @@ -2089,7 +2171,7 @@ void fanAuto() { } catch (ex) { log.error "fanAuto Exception:", ex - exceptionDataHandler(ex.message, "fanAuto") + exceptionDataHandler(ex?.message, "fanAuto") } } @@ -2125,30 +2207,31 @@ def lastN(String input, n) { } void Logger(msg, logType = "debug") { - def smsg = state?.showLogNamePrefix ? "${device.displayName}: ${msg}" : "${msg}" - switch (logType) { - case "trace": - log.trace "|| ${smsg}" - break - case "debug": - log.debug "${smsg}" - break - case "info": - log.info "||| ${smsg}" - break - case "warn": - log.warn "|| ${smsg}" - break - case "error": - log.error "| ${smsg}" - break - default: - log.debug "${smsg}" - break - } + def smsg = state?.showLogNamePrefix ? "${device.displayName} (v${devVer()}) | ${msg}" : "${msg}" def theId = lastN(device.getId().toString(),5) if(state?.enRemDiagLogging) { parent.saveLogtoRemDiagStore(smsg, logType, "Thermostat-${theId}") + } else { + switch (logType) { + case "trace": + log.trace "|| ${smsg}" + break + case "debug": + log.debug "${smsg}" + break + case "info": + log.info "||| ${smsg}" + break + case "warn": + log.warn "|| ${smsg}" + break + case "error": + log.error "| ${smsg}" + break + default: + log.debug "${smsg}" + break + } } } @@ -2185,78 +2268,39 @@ def exceptionDataHandler(msg, methodName) { def getFileBase64(url, preType, fileType) { try { - def params = [ - uri: url, - contentType: '$preType/$fileType' - ] + def params = [uri: url, contentType: "$preType/$fileType"] httpGet(params) { resp -> - if(resp.data) { - def respData = resp?.data - ByteArrayOutputStream bos = new ByteArrayOutputStream() - int len - int size = 4096 - byte[] buf = new byte[size] - while ((len = respData.read(buf, 0, size)) != -1) - bos.write(buf, 0, len) - buf = bos.toByteArray() - //LogAction("buf: $buf") - String s = buf?.encodeBase64() - //LogAction("resp: ${s}") - return s ? "data:${preType}/${fileType};base64,${s.toString()}" : null + if(resp?.status == 200) { + if(resp.data) { + def respData = resp?.data + byte[] byteData = resp?.data?.getBytes() + String enc = byteData?.encodeBase64() + // log.debug "enc: ${enc}" + return enc ? "data:${preType}/${fileType};base64,${enc?.toString()}" : null + } + } else { + LogAction("getFileBase64 Resp: ${resp?.status} ${url}", "error") + exceptionDataHandler("resp ${ex?.response?.status} ${url}", "getFileBase64") + return null } } - } - catch (ex) { - log.error "getFileBase64 Exception:", ex - exceptionDataHandler(ex.message, "getFileBase64") - } -} - -def getCssData() { - def cssData = null - def htmlInfo = state?.htmlInfo - if(htmlInfo?.cssUrl && htmlInfo?.cssVer) { - cssData = getFileBase64(htmlInfo.cssUrl, "text", "css") - state?.cssVer = htmlInfo?.cssVer - } else { - cssData = getFileBase64(cssUrl(), "text", "css") - } - return cssData -} - -def getChartJsData() { - def chartJsData = null - //def htmlInfo = state?.htmlInfo - def htmlInfo - state.chartJsData = null - - if(htmlInfo?.chartJsUrl && htmlInfo?.chartJsVer) { - if(state?.chartJsData) { - if(state?.chartJsVer?.toInteger() == htmlInfo?.chartJsVer?.toInteger()) { - //LogAction("getChartJsData: Chart Javascript Data is Current | Loading Data from State...") - chartJsData = state?.chartJsData - } else if(state?.chartJsVer?.toInteger() < htmlInfo?.chartJsVer?.toInteger()) { - //LogAction("getChartJsData: Chart Javascript Data is Outdated | Loading Data from Source...") - //chartJsData = getFileBase64(htmlInfo.chartJsUrl, "text", "javascript") - state.chartJsData = chartJsData - state?.chartJsVer = htmlInfo?.chartJsVer + } catch (ex) { + if(ex instanceof groovyx.net.http.ResponseParseException) { + if(ex?.statusCode != 200) { + LogAction("getFileBase64 Resp: ${ex?.statusCode} ${url}", "error") + log.error "getFileBase64 Exception:", ex } + } else if(ex instanceof groovyx.net.http.HttpResponseException && ex?.response) { + LogAction("getFileBase64 Resp: ${ex?.response?.status} ${url}", "error") + exceptionDataHandler("${ex?.response?.status} ${url}", "getFileBase64") } else { - //LogAction("getChartJsData: Chart Javascript Data is Missing | Loading Data from Source...") - chartJsData = getFileBase64(htmlInfo.chartJsUrl, "text", "javascript") - state?.chartJsData = chartJsData - state?.chartJsVer = htmlInfo?.chartJsVer + log.error "getFileBase64 Exception:", ex + exceptionDataHandler(ex, "getFileBase64") } - } else { - //LogAction("getChartJsData: No Stored Chart Javascript Data Found for Device... Loading for Static URL...") - chartJsData = getFileBase64(chartJsUrl(), "text", "javascript") - } - return chartJsData + return null + } } -def cssUrl() { return "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Documents/css/ST-HTML.min.css" } -def chartJsUrl() { return "https://www.gstatic.com/charts/loader.js" } - def getImg(imgName) { return imgName ? "https://cdn.rawgit.com/tonesto7/nest-manager/master/Images/Devices/$imgName" : "" } def getWebData(params, desc, text=true) { @@ -2528,7 +2572,7 @@ void getSomeData(devpoll = false) { // hackery to test getting old data def tryNum = 2 - if(state.eric != tryNum ) { + if(state?.eric != tryNum ) { if(devpoll) { runIn( 33, "getSomeData", [overwrite: true]) return @@ -2703,101 +2747,108 @@ def updateOperatingHistory(today) { } if(dayChange) { - def Op_coolingusage = getSumUsage(state.operatingStateTableYesterday, "cooling").toInteger() - def Op_heatingusage = getSumUsage(state.operatingStateTableYesterday, "heating").toInteger() - def Op_idle = getSumUsage(state.operatingStateTableYesterday, "idle").toInteger() - def Op_fanonly = getSumUsage(state.operatingStateTableYesterday, "fan only").toInteger() - def fan_on = getSumUsage(state.fanModeTableYesterday, "on").toInteger() - def fan_auto = getSumUsage(state.fanModeTableYesterday, "auto").toInteger() - - log.info "fanon ${fan_on} fanauto: ${fan_auto} opidle: ${Op_idle} cool: ${Op_coolingusage} heat: ${Op_heatingusage} fanonly: ${Op_fanonly}" - - hm."OperatingState_Day${hm.currentDay}_cooling" = Op_coolingusage - hm."OperatingState_Day${hm.currentDay}_heating" = Op_heatingusage - hm."OperatingState_Day${hm.currentDay}_idle" = Op_idle - hm."OperatingState_Day${hm.currentDay}_fanonly" = Op_fanonly - hm."FanMode_Day${hm.currentDay}_On" = fan_on - hm."FanMode_Day${hm.currentDay}_auto" = fan_auto - - hm.currentDay = dayNum - hm.OperatingState_DayWeekago_cooling = hm."OperatingState_Day${hm.currentDay}_cooling" - hm.OperatingState_DayWeekago_heating = hm."OperatingState_Day${hm.currentDay}_heating" - hm.OperatingState_DayWeekago_idle = hm."OperatingState_Day${hm.currentDay}_idle" - hm.OperatingState_DayWeekago_fanonly = hm."OperatingState_Day${hm.currentDay}_fanonly" - hm.FanMode_DayWeekago_On = hm."FanMode_Day${hm.currentDay}_On" - hm.FanMode_DayWeekago_auto = hm."FanMode_Day${hm.currentDay}_auto" - hm."OperatingState_Day${hm.currentDay}_cooling" = 0L - hm."OperatingState_Day${hm.currentDay}_heating" = 0L - hm."OperatingState_Day${hm.currentDay}_idle" = 0L - hm."OperatingState_Day${hm.currentDay}_fanonly" = 0L - hm."FanMode_Day${hm.currentDay}_On" = 0L - hm."FanMode_Day${hm.currentDay}_auto" = 0L - - def t1 = hm["OperatingState_Month${hm.currentMonth}_cooling"]?.toInteger() ?: 0L - hm."OperatingState_Month${hm.currentMonth}_cooling" = t1 + Op_coolingusage - t1 = hm["OperatingState_Month${hm.currentMonth}_heating"]?.toInteger() ?: 0L - hm."OperatingState_Month${hm.currentMonth}_heating" = t1 + Op_heatingusage - t1 = hm["OperatingState_Month${hm.currentMonth}_idle"]?.toInteger() ?: 0L - hm."OperatingState_Month${hm.currentMonth}_idle" = t1 + Op_idle - t1 = hm["OperatingState_Month${hm.currentMonth}_fanonly"]?.toInteger() ?: 0L - hm."OperatingState_Month${hm.currentMonth}_fanonly" = t1 + Op_fanonly - t1 = hm["FanMode_Month${hm.currentMonth}_On"]?.toInteger() ?: 0L - hm."FanMode_Month${hm.currentMonth}_On" = t1 + fan_on - t1 = hm["FanMode_Month${hm.currentMonth}_auto"]?.toInteger() ?: 0L - hm."FanMode_Month${hm.currentMonth}_auto" = t1 + fan_auto - - if(monthChange) { - hm.currentMonth = monthNum - hm.OperatingState_MonthYearago_cooling = hm."OperatingState_Month${hm.currentMonth}_cooling" - hm.OperatingState_MonthYearago_heating = hm."OperatingState_Month${hm.currentMonth}_heating" - hm.OperatingState_MonthYearago_idle = hm."OperatingState_Month${hm.currentMonth}_idle" - hm.OperatingState_MonthYearago_fanonly = hm."OperatingState_Month${hm.currentMonth}_fanonly" - hm.FanMode_MonthYearago_On = hm."FanMode_Month${hm.currentMonth}_On" - hm.FanMode_MonthYearago_auto = hm."FanMode_Month${hm.currentMonth}_auto" - hm."OperatingState_Month${hm.currentMonth}_cooling" = 0L - hm."OperatingState_Month${hm.currentMonth}_heating" = 0L - hm."OperatingState_Month${hm.currentMonth}_idle" = 0L - hm."FanMode_Month${hm.currentMonth}_On" = 0L - hm."FanMode_Month${hm.currentMonth}_auto" = 0L - } + try { + long Op_coolingusage = getSumUsage(state.operatingStateTableYesterday, "cooling") + long Op_heatingusage = getSumUsage(state.operatingStateTableYesterday, "heating") + long Op_idle = getSumUsage(state.operatingStateTableYesterday, "idle") + long Op_fanonly = getSumUsage(state.operatingStateTableYesterday, "fan only") + long fan_on = getSumUsage(state.fanModeTableYesterday, "on") + long fan_auto = getSumUsage(state.fanModeTableYesterday, "auto") + + log.info "fanon ${fan_on} fanauto: ${fan_auto} opidle: ${Op_idle} cool: ${Op_coolingusage} heat: ${Op_heatingusage} fanonly: ${Op_fanonly}" + + hm."OperatingState_Day${hm.currentDay}_cooling" = Op_coolingusage + hm."OperatingState_Day${hm.currentDay}_heating" = Op_heatingusage + hm."OperatingState_Day${hm.currentDay}_idle" = Op_idle + hm."OperatingState_Day${hm.currentDay}_fanonly" = Op_fanonly + hm."FanMode_Day${hm.currentDay}_On" = fan_on + hm."FanMode_Day${hm.currentDay}_auto" = fan_auto + + hm.currentDay = dayNum + hm.OperatingState_DayWeekago_cooling = hm."OperatingState_Day${hm.currentDay}_cooling" + hm.OperatingState_DayWeekago_heating = hm."OperatingState_Day${hm.currentDay}_heating" + hm.OperatingState_DayWeekago_idle = hm."OperatingState_Day${hm.currentDay}_idle" + hm.OperatingState_DayWeekago_fanonly = hm."OperatingState_Day${hm.currentDay}_fanonly" + hm.FanMode_DayWeekago_On = hm."FanMode_Day${hm.currentDay}_On" + hm.FanMode_DayWeekago_auto = hm."FanMode_Day${hm.currentDay}_auto" + hm."OperatingState_Day${hm.currentDay}_cooling" = 0L + hm."OperatingState_Day${hm.currentDay}_heating" = 0L + hm."OperatingState_Day${hm.currentDay}_idle" = 0L + hm."OperatingState_Day${hm.currentDay}_fanonly" = 0L + hm."FanMode_Day${hm.currentDay}_On" = 0L + hm."FanMode_Day${hm.currentDay}_auto" = 0L + + long t1 = hm?."OperatingState_Month${hm.currentMonth}_cooling"?.toInteger() ?: 0L + hm."OperatingState_Month${hm.currentMonth}_cooling" = t1 + Op_coolingusage + t1 = hm?."OperatingState_Month${hm.currentMonth}_heating"?.toInteger() ?: 0L + hm."OperatingState_Month${hm.currentMonth}_heating" = t1 + Op_heatingusage + t1 = hm?."OperatingState_Month${hm.currentMonth}_idle"?.toInteger() ?: 0L + hm."OperatingState_Month${hm.currentMonth}_idle" = t1 + Op_idle + t1 = hm?."OperatingState_Month${hm.currentMonth}_fanonly"?.toInteger() ?: 0L + hm."OperatingState_Month${hm.currentMonth}_fanonly" = t1 + Op_fanonly + t1 = hm?."FanMode_Month${hm.currentMonth}_On"?.toInteger() ?: 0L + hm."FanMode_Month${hm.currentMonth}_On" = t1 + fan_on + t1 = hm?."FanMode_Month${hm.currentMonth}_auto"?.toInteger() ?: 0L + hm."FanMode_Month${hm.currentMonth}_auto" = t1 + fan_auto + + if(monthChange) { + hm.currentMonth = monthNum + hm.OperatingState_MonthYearago_cooling = hm."OperatingState_Month${hm.currentMonth}_cooling" + hm.OperatingState_MonthYearago_heating = hm."OperatingState_Month${hm.currentMonth}_heating" + hm.OperatingState_MonthYearago_idle = hm."OperatingState_Month${hm.currentMonth}_idle" + hm.OperatingState_MonthYearago_fanonly = hm."OperatingState_Month${hm.currentMonth}_fanonly" + hm.FanMode_MonthYearago_On = hm."FanMode_Month${hm.currentMonth}_On" + hm.FanMode_MonthYearago_auto = hm."FanMode_Month${hm.currentMonth}_auto" + hm."OperatingState_Month${hm.currentMonth}_cooling" = 0L + hm."OperatingState_Month${hm.currentMonth}_heating" = 0L + hm."OperatingState_Month${hm.currentMonth}_idle" = 0L + hm."FanMode_Month${hm.currentMonth}_On" = 0L + hm."FanMode_Month${hm.currentMonth}_auto" = 0L + } - t1 = hm[OperatingState_thisYear_cooling]?.toInteger() ?: 0L - hm.OperatingState_thisYear_cooling = t1 + Op_coolingusage - t1 = hm[OperatingState_thisYear_heating]?.toInteger() ?: 0L - hm.OperatingState_thisYear_heating = t1 + Op_heatingusage - t1 = hm[OperatingState_thisYear_idle]?.toInteger() ?: 0L - hm.OperatingState_thisYear_idle = t1 + Op_idle - t1 = hm[OperatingState_thisYear_fanonly]?.toInteger() ?: 0L - hm.OperatingState_thisYear_fanonly = t1 + Op_fanonly - t1 = hm[FanMode_thisYear_On]?.toInteger() ?: 0L - hm.FanMode_thisYear_On = t1 + fan_on - t1 = hm[FanMode_thisYear_auto]?.toInteger() ?: 0L - hm.FanMode_thisYear_auto = t1 + fan_auto - - if(yearChange) { - hm.currentYear = yearNum - hm.OperatingState_lastYear_cooling = hm.OperatingState_thisYear_cooling - hm.OperatingState_lastYear_heating = hm.OperatingState_thisYear_heating - hm.OperatingState_lastYear_idle = hm.OperatingState_thisYear_idle - hm.OperatingState_lastYear_fanonly = hm.OperatingState_thisYear_fanonly - hm.FanMode_lastYear_On = hm.FanMode_thisYear_On - hm.FanMode_lastYear_auto = hm.FanMode_thisYear_auto - - hm.OperatingState_thisYear_cooling = 0L - hm.OperatingState_thisYear_heating = 0L - hm.OperatingState_thisYear_idle = 0L - hm.OperatingState_thisYear_fanonly = 0L - hm.FanMode_thisYear_On = 0L - hm.FanMode_thisYear_auto = 0L + t1 = hm?.OperatingState_thisYear_cooling?.toInteger() ?: 0L + hm.OperatingState_thisYear_cooling = t1 + Op_coolingusage + t1 = hm?.OperatingState_thisYear_heating?.toInteger() ?: 0L + hm.OperatingState_thisYear_heating = t1 + Op_heatingusage + t1 = hm?.OperatingState_thisYear_idle?.toInteger() ?: 0L + hm.OperatingState_thisYear_idle = t1 + Op_idle + t1 = hm?.OperatingState_thisYear_fanonly?.toInteger() ?: 0L + hm.OperatingState_thisYear_fanonly = t1 + Op_fanonly + t1 = hm?.FanMode_thisYear_On?.toInteger() ?: 0L + hm.FanMode_thisYear_On = t1 + fan_on + t1 = hm?.FanMode_thisYear_auto?.toInteger() ?: 0L + hm.FanMode_thisYear_auto = t1 + fan_auto + + if(yearChange) { + hm.currentYear = yearNum + hm.OperatingState_lastYear_cooling = hm.OperatingState_thisYear_cooling + hm.OperatingState_lastYear_heating = hm.OperatingState_thisYear_heating + hm.OperatingState_lastYear_idle = hm.OperatingState_thisYear_idle + hm.OperatingState_lastYear_fanonly = hm.OperatingState_thisYear_fanonly + hm.FanMode_lastYear_On = hm.FanMode_thisYear_On + hm.FanMode_lastYear_auto = hm.FanMode_thisYear_auto + + hm.OperatingState_thisYear_cooling = 0L + hm.OperatingState_thisYear_heating = 0L + hm.OperatingState_thisYear_idle = 0L + hm.OperatingState_thisYear_fanonly = 0L + hm.FanMode_thisYear_On = 0L + hm.FanMode_thisYear_auto = 0L + } + state.historyStoreMap = hm + + } catch (ex) { + state.eric = 0 // force clear of stats + state.remove("historyStoreMap") + log.error "updateOperatingHistory Exception:", ex } - state.historyStoreMap = hm } } def getSumUsage(table, String strtyp) { //log.trace "getSumUsage...$strtyp Table size: ${table?.size()}" - def totseconds = 0L - def newseconds = 0L + long totseconds = 0L + long newseconds = 0L def hr def mins @@ -2845,7 +2896,7 @@ def getSumUsage(table, String strtyp) { } //log.info "$strtyp totseconds: $totseconds" - return totseconds.toInteger() + return totseconds } def initHistoryStore() { @@ -3015,12 +3066,12 @@ def getHistoryStore() { } def hm = thm.clone() - def Op_coolingusage = getSumUsage(state.operatingStateTable, "cooling").toInteger() - def Op_heatingusage = getSumUsage(state.operatingStateTable, "heating").toInteger() - def Op_idle = getSumUsage(state.operatingStateTable, "idle").toInteger() - def Op_fanonly = getSumUsage(state.operatingStateTable, "fan only").toInteger() - def fan_on = getSumUsage(state.fanModeTable, "on").toInteger() - def fan_auto = getSumUsage(state.fanModeTable, "auto").toInteger() + long Op_coolingusage = getSumUsage(state.operatingStateTable, "cooling") + long Op_heatingusage = getSumUsage(state.operatingStateTable, "heating") + long Op_idle = getSumUsage(state.operatingStateTable, "idle") + long Op_fanonly = getSumUsage(state.operatingStateTable, "fan only") + long fan_on = getSumUsage(state.fanModeTable, "on") + long fan_auto = getSumUsage(state.fanModeTable, "auto") //log.info "fanon ${fan_on} fanauto: ${fan_auto} opidle: ${Op_idle} cool: ${Op_coolingusage} heat: ${Op_heatingusage}" //log.debug "currentDay ${hm.currentDay} | currentMonth ${hm.currentMonth} | currentYear: ${hm.currentYear}" @@ -3032,30 +3083,30 @@ def getHistoryStore() { hm."FanMode_Day${hm.currentDay}_On" = fan_on hm."FanMode_Day${hm.currentDay}_auto" = fan_auto - def t1 = hm["OperatingState_Month${hm.currentMonth}_cooling"]?.toInteger() ?: 0L + long t1 = hm?."OperatingState_Month${hm.currentMonth}_cooling"?.toInteger() ?: 0L hm."OperatingState_Month${hm.currentMonth}_cooling" = t1 + Op_coolingusage - t1 = hm["OperatingState_Month${hm.currentMonth}_heating"]?.toInteger() ?: 0L + t1 = hm?."OperatingState_Month${hm.currentMonth}_heating"?.toInteger() ?: 0L hm."OperatingState_Month${hm.currentMonth}_heating" = t1 + Op_heatingusage - t1 = hm["OperatingState_Month${hm.currentMonth}_idle"]?.toInteger() ?: 0L + t1 = hm?."OperatingState_Month${hm.currentMonth}_idle"?.toInteger() ?: 0L hm."OperatingState_Month${hm.currentMonth}_idle" = t1 + Op_idle - t1 = hm["OperatingState_Month${hm.currentMonth}_fanonly"]?.toInteger() ?: 0L + t1 = hm?."OperatingState_Month${hm.currentMonth}_fanonly"?.toInteger() ?: 0L hm."OperatingState_Month${hm.currentMonth}_fanonly" = t1 + Op_fanonly - t1 = hm["FanMode_Month${hm.currentMonth}_On"]?.toInteger() ?: 0L + t1 = hm?."FanMode_Month${hm.currentMonth}_On"?.toInteger() ?: 0L hm."FanMode_Month${hm.currentMonth}_On" = t1 + fan_on - t1 = hm["FanMode_Month${hm.currentMonth}_auto"]?.toInteger() ?: 0L + t1 = hm?."FanMode_Month${hm.currentMonth}_auto"?.toInteger() ?: 0L hm."FanMode_Month${hm.currentMonth}_auto" = t1 + fan_auto - t1 = hm[OperatingState_thisYear_cooling]?.toInteger() ?: 0L + t1 = hm?.OperatingState_thisYear_cooling?.toInteger() ?: 0L hm.OperatingState_thisYear_cooling = t1 + Op_coolingusage - t1 = hm[OperatingState_thisYear_heating]?.toInteger() ?: 0L + t1 = hm?.OperatingState_thisYear_heating?.toInteger() ?: 0L hm.OperatingState_thisYear_heating = t1 + Op_heatingusage - t1 = hm[OperatingState_thisYear_idle]?.toInteger() ?: 0L + t1 = hm?.OperatingState_thisYear_idle?.toInteger() ?: 0L hm.OperatingState_thisYear_idle = t1 + Op_idle - t1 = hm[OperatingState_thisYear_fanonly]?.toInteger() ?: 0L + t1 = hm?.OperatingState_thisYear_fanonly?.toInteger() ?: 0L hm.OperatingState_thisYear_fanonly = t1 + Op_fanonly - t1 = hm[FanMode_thisYear_On]?.toInteger() ?: 0L + t1 = hm?.FanMode_thisYear_On?.toInteger() ?: 0L hm.FanMode_thisYear_On = t1 + fan_on - t1 = hm[FanMode_thisYear_auto]?.toInteger() ?: 0L + t1 = hm?.FanMode_thisYear_auto?.toInteger() ?: 0L hm.FanMode_thisYear_auto = t1 + fan_auto return hm @@ -3130,7 +3181,7 @@ def getIntListAvg(itemList) { def iCnt = itemList?.size() if(iCnt >= 1) { if(iCnt > 1) { - avgRes = (itemList?.sum().toDouble() / iCnt.toDouble()).round(0) // + avgRes = (itemList?.sum().toDouble() / iCnt.toDouble()).round(0) } else { itemList?.each { avgRes = avgRes + it.toInteger() } } } //log.debug "[getIntListAvg] avgRes: $avgRes" @@ -3139,10 +3190,10 @@ def getIntListAvg(itemList) { def secToTimeMap(long seconds) { long sec = (seconds % 60) ?: 0L - long minutes = ((seconds % 3600) / 60) ?: 0L // - long hours = ((seconds % 86400) / 3600) ?: 0L // - long days = (seconds / 86400) ?: 0L // - long years = (days / 365) ?: 0L // + long minutes = ((seconds % 3600) / 60) ?: 0L + long hours = ((seconds % 86400) / 3600) ?: 0L + long days = (seconds / 86400) ?: 0L + long years = (days / 365) ?: 0L def res = ["m":minutes, "h":hours, "d":days, "y":years] return res } @@ -3222,7 +3273,7 @@ def getChgLogHtml() { if(!state?.shownChgLog == true) { chgStr = """ - + - - + + + + + + + @@ -3400,7 +3450,7 @@ def getGraphHTML() { ${devBrdCastHtml} ${clientBl} ${updateAvail} -
+
@@ -3476,10 +3526,7 @@ def getGraphHTML() {
- -
-

Swipe-Tap to Change Slide

-
+
@@ -3530,14 +3575,259 @@ def getGraphHTML() { render contentType: "text/html", data: html, status: 200 } catch (ex) { log.error "graphHTML Exception:", ex - exceptionDataHandler(ex.message, "graphHTML") + exceptionDataHandler(ex?.message, "graphHTML") + } +} + +def hasHtml() { return true } + +def getDeviceTile(devNum) { + try { + def tempStr = "\u00b0F" + if( wantMetric() ) { + tempStr = "\u00b0C" + } + checkVirtualStatus() + //LogAction("State Size: ${getStateSize()} (${getStateSizePerc()}%)") + def canHeat = state?.can_heat == true ? true : false + def canCool = state?.can_cool == true ? true : false + def hasFan = state?.has_fan == true ? true : false + def leafImg = state?.hasLeaf ? getImg("nest_leaf_on.gif") : getImg("nest_leaf_off.gif") + def updateAvail = !state.updateAvailable ? "" : """
Device Update Available!
""" + def clientBl = state?.clientBl ? """
Your Manager client has been blacklisted!\nPlease contact the Nest Manager developer to get the issue resolved!!!
""" : "" + + def timeToTarget = device.currentState("timeToTarget").stringValue + def sunCorrectStr = state?.sunCorrectEnabled ? "Enabled (${state?.sunCorrectActive == true ? "Active" : "Inactive"})" : "Disabled" + def refreshBtnHtml = state.mobileClientType == "ios" ? + """
""" : "" + def chartHtml = ( + state?.showGraphs && + state?.temperatureTable?.size() > 0 && + state?.operatingStateTable?.size() > 0 && + state?.temperatureTableYesterday?.size() > 0 && + state?.humidityTable?.size() > 0 && + state?.coolSetpointTable?.size() > 0 && + state?.heatSetpointTable?.size() > 0) ? showChartHtml(devNum) : (state?.showGraphs ? hideChartHtml() : "") + + def whoSetEco = device?.currentValue("whoSetEcoMode") + def whoSetEcoDt = state?.ecoDescDt + def ecoDesc = whoSetEco && !(whoSetEco in ["Not in Eco Mode", "Unknown", "Not Set", "Set Outside of this DTH", "A ST Automation", "User Changed (ST)"]) ? "Eco Set By: ${getAutoChgType(whoSetEco)}" : "${whoSetEco}" + + def ecoDescDt = whoSetEcoDt != null ? """
${whoSetEcoDt ?: ""}
+ + + + + + + +
Active Schedule
#${schedData?.scdNum} - ${schedData?.schedName}
+

Zone Status

+ + + + + + + + + + + + + + +
Temp Source:Zone Temp:
${schedData?.tempSrcDesc}${schedData?.curZoneTemp}°${state?.tempUnit}
+ + + + + + + + + + + + + +
Desired Heat TempDesired Cool Temp
${schedData?.reqSenHeatSetPoint ? "${schedData?.reqSenHeatSetPoint}°${state?.tempUnit}": "Not Available"}${schedData?.reqSenCoolSetPoint ? "${schedData?.reqSenCoolSetPoint}°${state?.tempUnit}": "Not Available"}
+
+
+ """ + } + + def chgDescHtml = """ + ${schedHtml == "" ? "" : """
"""} +
+

Last Automation Event

+ + + + + + + + + +
${getAutoChgType(device?.currentValue("whoMadeChanges"))}
${device?.currentValue("whoMadeChangesDesc") ?: "Unknown"}
${device?.currentValue("whoMadeChangesDescDt") ?: ""}
+
+
+
+

Eco Set By

+ + + + ${ecoDescDt} + +
${ecoDesc}
+
+ ${schedHtml == "" ? "" : """
"""} + """ + + def html = """ + ${clientBl} + ${updateAvail} +
+
+ +
+ +
+ ${schedHtml == "" ? "" : "${schedHtml}"} +
+

Device Info

+ + + + + + + + + + + + + +
Time to TargetSun Correction
${timeToTarget}${sunCorrectStr}
+ + + + + + + + + + + + ${state?.onlineStatus.toString().capitalize()} + + ${state?.apiStatus} + + +
Network StatusLeafAPI Status
+ + + + + + + + + + + + + + + + +
Firmware VersionDebugDevice Type
${state?.softwareVer.toString()}${state?.debugStatus}${state?.devTypeVer.toString()}
+ + + + + + + + + + + +
Nest Checked-InData Last Received
${state?.lastConnection.toString()}${state?.lastUpdatedDt.toString()}
+
+ ${schedHtml == "" ? """
${chgDescHtml}""" : ""} +
+ ${schedHtml == "" ? "" : """${chgDescHtml}"""} + ${chartHtml} +
+ +
+

Swipe/Drag to Change Slide

+
+
+
+
+ + """ + render contentType: "text/html", data: html, status: 200 + } catch (ex) { + log.error "getDeviceTile Exception:", ex + exceptionDataHandler(ex?.message, "getDeviceTile") } } -def showChartHtml() { - def tempStr = "°F" +def showChartHtml(devNum="") { + def tempStr = "\u00b0F" if( wantMetric() ) { - tempStr = "°C" + tempStr = "\u00b0C" } def canHeat = state?.can_heat == true ? true : false def canCool = state?.can_cool == true ? true : false @@ -3636,12 +3926,12 @@ def showChartHtml() { //TODO fix for fanonly grpUseData?.each { mon -> def data = mon?.value - def heat = data?.heating ? (data?.heating?.tSec.toLong()/3600).toDouble().round(0) : 0 // - def cool = data?.cooling ? (data?.cooling?.tSec.toLong()/3600).toDouble().round(0) : 0 // - def idle = data?.idle ? (data?.idle?.tSec.toLong()/3600).toDouble().round(0) : 0 // - def fanonly = data?.fanonly ? (data?.fanonly?.tSec.toLong()/3600).toDouble().round(0) : 0 // - def fanOn = data?.fanOn ? (data?.fanOn?.tSec.toLong()/3600).toDouble().round(0) : 0 // - def fanAuto = data?.fanAuto ? (data?.fanAuto?.tSec.toLong()/3600).toDouble().round(0) : 0 // + def heat = data?.heating ? (data?.heating?.tSec.toLong()/3600).toDouble().round(0) : 0 + def cool = data?.cooling ? (data?.cooling?.tSec.toLong()/3600).toDouble().round(0) : 0 + def idle = data?.idle ? (data?.idle?.tSec.toLong()/3600).toDouble().round(0) : 0 + def fanonly = data?.fanonly ? (data?.fanonly?.tSec.toLong()/3600).toDouble().round(0) : 0 + def fanOn = data?.fanOn ? (data?.fanOn?.tSec.toLong()/3600).toDouble().round(0) : 0 + def fanAuto = data?.fanAuto ? (data?.fanAuto?.tSec.toLong()/3600).toDouble().round(0) : 0 def mName = getMonthNumToStr(mon?.key) lStr += "\n$mName Usage - Idle: ($idle) | Heat: ($heat) | Cool: ($cool) | Fanonly: (${fanonly}) FanOn: ($fanOn) | FanAuto: ($fanAuto)" def iNum = 1 @@ -3687,10 +3977,10 @@ def showChartHtml() { def data = """ " return dayName + forecastImageLink + modalHead + modalTitle + forecastImage + forecastTxt + modalClose @@ -1622,16 +1671,14 @@ def getChgLogHtml() { return chgStr } +def hasHtml() { return true } + def getWeatherHTML() { try { - if(!state?.curWeather || !state?.curForecast) { - return hideWeatherHtml() - } + if(!state?.curWeather || !state?.curForecast) { return hideWeatherHtml() } def updateAvail = !state.updateAvailable ? "" : """
Device Update Available!
""" def clientBl = state?.clientBl ? """
Your Manager client has been blacklisted!\nPlease contact the Nest Manager developer to get the issue resolved!!!
""" : "" - //def obsrvTime = "Last Updated:\n${convertRfc822toDt(state?.curWeather?.current_observation?.observation_time_rfc822)}" - def obsrvTime = "Last Updated:\n${state?.curWeather?.current_observation?.observation_time_rfc822}" - + def obsrvTime = "Last Updated:\n${state?.curWeather?.validTimeLocal}" def devBrdCastData = state?.devBannerData ?: null def devBrdCastHtml = "" if(devBrdCastData) { @@ -1657,17 +1704,16 @@ def getWeatherHTML() { - - - - - - - - + + + + - + + + + @@ -1679,42 +1725,42 @@ def getWeatherHTML() { ${clientBl} ${updateAvail} ${getWeatherAlertHtml()} -
+

Current Weather Conditions

-

${state?.curWeather?.current_observation?.display_location?.full}

+

${state?.curWeatherLoc}

Feels Like: ${getFeelslike()}
Precip %: ${device.currentState("percentPrecip")?.value}%
Precip: ${getPrecip()}
- Humidity: ${state?.curWeather?.current_observation?.relative_humidity}
+ Humidity: ${state?.curWeatherHum}
Dew Point: ${getDewpoint()}
Pressure: ${getPressure()}
- UV Index: ${state.curWeather?.current_observation?.UV}
+ UV Index: ${device.currentState("ultravioletIndex")?.value}
Visibility: ${getVisibility()}
Lux: ${getLux()}
Sunrise: ${state?.localSunrise}
Sunset: ${state?.localSunset}
Wind: ${state?.windStr}
-
+

${getTemp()}

${state.curWeatherCond}

-
${forecastDay(0)}
${forecastDay(1)}
${forecastDay(2)}
+
${forecastDay(3)}
-
${forecastDay(3)}
${forecastDay(4)}
${forecastDay(5)}
+
${forecastDay(6)}
-
${forecastDay(6)}
-
${forecastDay(7)}
+
${forecastDay(7)}
+
${forecastDay(8)}

Tap Icon to View Forecast

@@ -1722,20 +1768,17 @@ def getWeatherHTML() {
- Station Id: ${state?.curWeather?.current_observation?.station_id} - ${state?.curWeather?.current_observation?.observation_time} + ${state?.curWeather?.validTimeLocal}
-
@@ -1743,16 +1786,90 @@ def getWeatherHTML() { """ +/* """ */ incHtmlLoadCnt() render contentType: "text/html", data: mainHtml, status: 200 } catch (ex) { log.error "getWeatherHTML Exception:", ex - exceptionDataHandler(ex.message, "getWeatherHTML") + exceptionDataHandler(ex?.message, "getWeatherHTML") + } +} + +def getDeviceTile(devNum="") { + try { + if(!state?.curWeather || !state?.curForecast) { + return hideWeatherHtml() + } + def updateAvail = !state.updateAvailable ? "" : """
Device Update Available!
""" + def clientBl = state?.clientBl ? """
Your Manager client has been blacklisted!\nPlease contact the Nest Manager developer to get the issue resolved!!!
""" : "" + def obsrvTime = "Last Updated:\n${state?.curWeather?.validTimeLocal}" + + def mainHtml = """ + ${clientBl} + ${updateAvail} + ${getWeatherAlertHtml()} +
+
+

Current Weather Conditions

+

${state?.curWeatherLoc}

+
+
+ Feels Like: ${getFeelslike()}
+ Precip %: ${device.currentState("percentPrecip")?.value}%
+ Precip: ${getPrecip()}
+ Humidity: ${state?.curWeatherHum}
+ Dew Point: ${getDewpoint()}
+ Pressure: ${getPressure()}
+ UV Index: ${device.currentState("ultravioletIndex")?.value}
+ Visibility: ${getVisibility()}
+ Lux: ${getLux()}
+ Sunrise: ${state?.localSunrise}
Sunset: ${state?.localSunset}
+ Wind: ${state?.windStr}
+
+
+
+

${getTemp()}

+

${state.curWeatherCond}

+
+
+
+
${forecastDay(1)}
+
${forecastDay(2)}
+
${forecastDay(3)}
+
+
+
${forecastDay(4)}
+
${forecastDay(5)}
+
${forecastDay(6)}
+
+
+
${forecastDay(7)}
+
${forecastDay(8)}
+
+

Tap Icon to View Forecast

+ + ${historyGraphHtml(devNum)} + +
+
+ ${state?.curWeather?.validTimeLocal} +
+
+
+
+ + """ +/* """ */ + render contentType: "text/html", data: mainHtml, status: 200 + } + catch (ex) { + log.error "getDeviceTile Exception:", ex + exceptionDataHandler(ex?.message, "getDeviceTile") } } -def historyGraphHtml() { +def historyGraphHtml(devNum="") { def html = "" if(state?.showGraphs) { if (state?.temperatureTable?.size() > 0 && state?.dewpointTable?.size() > 0) { @@ -1771,8 +1888,8 @@ def historyGraphHtml() { html = """

Event History

-
+
""" } else { html = """ diff --git a/installerManifest.json b/installerManifest.json new file mode 100644 index 000000000..79e51670d --- /dev/null +++ b/installerManifest.json @@ -0,0 +1,91 @@ +{ + "namespace": "tonesto7", + "repoOwner": "tonesto7", + "repoName": "nest-manager", + "repoBranch": "master", + "name": "NST Manager", + "author": "Anthony S.", + "description": "The Best Solution to integrate your Nest Products into the SmartThings Enviroment.", + "category": "My Apps", + "bannerUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/nst_manager_5_banner.png", + "forumUrl": "https://community.smartthings.com/t/release-nst-manager-v5-0/", + "docUrl": "http://thingsthataresmart.wiki/index.php?title=NST_Manager", + "releaseType": "production", + "keywords": [ + "nest", + "thermostat", + "nst", + "camera", + "protect", + "smoke", + "carbon", + "monoxide" + ], + "notes": "Nothing to show here (yet)", + "smartApps": { + "parent": { + "name": "Nest Manager", + "iconUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/nst_manager_5.png", + "published": true, + "oAuth": true, + "version": "5.6.4", + "appSettings": { + "clientId": "", + "clientSecret": "", + "devOpt": "false" + }, + "appUrl": "smartapps/tonesto7/nest-manager.src/nest-manager.groovy" + }, + "children": [{ + "name": "NST Automations", + "iconUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/nst_automations_5.png", + "published": true, + "oAuth": false, + "version": "5.5.0", + "appSettings": {}, + "appUrl": "smartapps/tonesto7/nst-automations.src/nst-automations.groovy", + "optional": false + }] + }, + "deviceHandlers": [{ + "name": "Nest Thermostat", + "iconUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/thermostat_icon.png", + "published": true, + "version": "5.4.6", + "appUrl": "deviceTypes/tonesto7/nest-thermostat.src/nest-thermostat.groovy", + "optional": false + }, + { + "name": "Nest Protect", + "iconUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/protect_icon.png", + "published": true, + "version": "5.4.3", + "appUrl": "deviceTypes/tonesto7/nest-protect.src/nest-protect.groovy", + "optional": false + }, + { + "name": "Nest Camera", + "iconUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/camera_icon.png", + "published": true, + "version": "5.4.5", + "appUrl": "deviceTypes/tonesto7/nest-camera.src/nest-camera.groovy", + "optional": false + }, + { + "name": "Nest Presence", + "iconUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/presence_icon.png", + "published": true, + "version": "5.4.4", + "appUrl": "deviceTypes/tonesto7/nest-presence.src/nest-presence.groovy", + "optional": true + }, + { + "name": "Nest Weather", + "iconUrl": "https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/App/weather_icon.png", + "published": true, + "version": "5.5.2", + "appUrl": "deviceTypes/tonesto7/nest-weather.src/nest-weather.groovy", + "optional": true + } + ] +} \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 000000000..69ca405e5 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "ES6" + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/smartapps/tonesto7/nest-manager.src/nest-manager.groovy b/smartapps/tonesto7/nest-manager.src/nest-manager.groovy index e7ef9ca43..bb05e7dd1 100644 --- a/smartapps/tonesto7/nest-manager.src/nest-manager.groovy +++ b/smartapps/tonesto7/nest-manager.src/nest-manager.groovy @@ -1,6 +1,6 @@ /******************************************************************************************** | Application Name: NST Manager | -| Copyright (C) 2017 Anthony S. | +| Copyright (C) 2017, 2018, 2019 Anthony S. | | Authors: Anthony S. (@tonesto7), Eric S. (@E_sch) | | Contributors: Ben W. (@desertblade) | | A few code methods are modeled from those in CoRE by Adrian Caramaliu | @@ -8,8 +8,8 @@ | License Info: https://github.com/tonesto7/nest-manager/blob/master/app_license.txt | | | | NOTE: I really hope that we don't have a ton of forks being released to the community, | -| and that we can collaborate to make the smartapp and devices that will accommodate | -| every use case | +| and that we can collaborate to make smartapps and devices that will accommodate to | +| all use cases | *********************************************************************************************/ import groovy.json.* @@ -23,11 +23,10 @@ definition( author: "${appAuthor()}", description: "${textDesc()}", category: "Convenience", - iconUrl: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_manager_icon.png", - iconX2Url: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_manager_icon%402x.png", - iconX3Url: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_manager_icon%403x.png", - singleInstance: true, - oauth: true ) + iconUrl: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_manager_5.png", + iconX2Url: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_manager_5%402x.png", + iconX3Url: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_manager_5%403x.png", + singleInstance: true) { appSetting "clientId" @@ -35,17 +34,17 @@ definition( appSetting "devOpt" } -def appVersion() { "5.2.3" } -def appVerDate() { "11-20-2017" } +def appVersion() { "5.6.4" } +def appVerDate() { "05-16-2019" } def minVersions() { return [ - "automation":["val":520, "desc":"5.2.0"], - "thermostat":["val":520, "desc":"5.2.0"], - "protect":["val":520, "desc":"5.2.0"], - "presence":["val":520, "desc":"5.2.0"], - "weather":["val":520, "desc":"5.2.0"], - "camera":["val":520, "desc":"5.2.0"], - "stream":["val":101, "desc":"1.0.1"] + "automation":["val":550, "desc":"5.5.0"], + "thermostat":["val":546, "desc":"5.4.6"], + "protect":["val":543, "desc":"5.4.3"], + "presence":["val":544, "desc":"5.4.4"], + "weather":["val":552, "desc":"5.5.2"], + "camera":["val":545, "desc":"5.4.5"], + "stream":["val":201, "desc":"2.0.1"] ] } @@ -57,6 +56,7 @@ preferences { page(name: "authPage") page(name: "mainPage") page(name: "deviceSelectPage") + page(name: "devWebTiles") page(name: "donationPage") page(name: "reviewSetupPage") page(name: "voiceRprtPrefPage") @@ -70,7 +70,7 @@ preferences { page(name: "devNamePage") page(name: "alarmTestPage") page(name: "simulateTestEventPage") - page(name: "devNameResetPage") +// page(name: "devNameResetPage") page(name: "resetDiagQueuePage") page(name: "devPrefPage") page(name: "camMotionZoneFltrPage") @@ -78,7 +78,6 @@ preferences { page(name: "nestTokenResetPage") page(name: "uninstallPage") page(name: "forceUninstallPage") - page(name: "diagnosticPage") page(name: "custWeatherPage") page(name: "automationsPage") page(name: "automationKickStartPage") @@ -87,7 +86,7 @@ preferences { page(name: "automationSchedulePage") page(name: "feedbackPage") page(name: "sendFeedbackPage") - + page(name: "codeUpdatesPage") page(name: "setNotificationPage") page(name: "notifConfigPage") page(name: "setNotificationTimePage") @@ -100,8 +99,19 @@ mappings { path("/oauth/initialize") {action: [GET: "oauthInitUrl"]} path("/oauth/callback") {action: [GET: "callback"]} + path("/deviceTiles") {action: [GET: "renderDeviceTiles"]} + path("/tstatTiles") {action: [GET: "getTstatTiles"]} + path("/protectTiles") {action: [GET: "getProtectTiles"]} + path("/cameraTiles") {action: [GET: "getCamTiles"]} + path("/weatherTile") {action: [GET: "getWeatherTile"]} + path("/renderInstallData") {action: [GET: "renderInstallData"]} + if(!(settings?.restStreamLocal && settings?.restStreamLocalHub)) { + path("/receiveEventData") {action: [POST: "receiveEventData"]} + path("/streamStatus") {action: [POST: "receiveStreamStatus"]} + } //Web Diagnostics Pages if(settings?.enDiagWebPage == true || getDevOpt()) { + path("/processCmd") {action: [POST: "procDiagCmd"]} path("/diagHome") {action: [GET: "renderDiagHome"]} path("/getLogData") {action: [GET: "renderLogData"]} //path("/getLogMap") {action: [GET: "getLogMap"]} @@ -111,26 +121,16 @@ mappings { path("/getInstData") {action: [GET: "renderInstData"]} path("/getAppData") {action: [GET: "renderAppData"]} } - // path("/execCmd/:command") {action: [GET: "execCmd"]} - // path("/setData/:value") {action: [GET: "getSetData", POST: "updateSetData", DELETE: "delSetData"]} - // path("/stateData/:value") {action: [GET: "getStateData", POST: "updateStateData", DELETE: "delStateData"]} - path("/renderInstallData") {action: [GET: "renderInstallData"]} - path("/receiveEventData") {action: [POST: "receiveEventData"]} - path("/streamStatus") {action: [POST: "receiveStreamStatus"]} } } /****************************************************************************** -| Application Pages | +| Application Pages | *******************************************************************************/ //This Page is used to load either parent or child app interface code def startPage() { - if(parent) { - atomicState?.isParent = false - } else { - atomicState?.isParent = true - authPage() - } + atomicState?.isParent = true + authPage() } def authPage() { @@ -146,19 +146,30 @@ def authPage() { if(!atomicState?.devHandlersTested) { deviceHandlerTest() } if(!atomicState?.accessToken || !nestDevAccountCheckOk() || (!atomicState?.isInstalled && (!atomicState?.devHandlersTested || !preReqOk)) || (stateSz > 80)) { - return dynamicPage(name: "authPage", title: "Status Page", nextPage: "", install: false, uninstall: false) { - section ("Status Page:") { + return dynamicPage(name: "authPage", title: "Status Page", nextPage: "", install: (atomicState?.isInstalled == true ? true : false), uninstall: false) { + section () { + def title = "" def desc = "" def showWiki = false + def wikiDesc = "View Instruction Projects Wiki" + def wikiObj = "" if(!atomicState?.accessToken) { - desc = "OAuth is not Enabled for ${appName()} application. Please click remove and review the installation directions again" + title = "OAuth Error" + desc = "OAuth is not Enabled for ${appName()} application. Please click remove and review the installation directions again" + wikiObj = "#Enabling_OAuth" + wikiDesc = "Enabling Oauth (Wiki)" } else if(!nestDevAccountCheckOk()) { - desc = "You are missing the Client ID and Secret.\n\nWe can no longer provide you with a built-in Nest Client ID and Secret. Please check the Wiki for Detailed instructions on creating your own Nest Dev ID and Secret." + title = "Nest Developer Data Missing" + desc = "Client ID and Secret\nAre both missing!\n\nThe built-in Client ID and Secret can no longer be provided.\n\nPlease visit the Wiki at the link below to resolve the issue." showWiki = true + wikiObj = "#Nest_Developer_Account" + wikiDesc = "Configure Nest Dev Account (Wiki)" } else if(!atomicState?.devHandlersTested) { - desc = "Device Handlers are Missing or Not Published. Please verify the installation instructions and device handlers are present before continuing." + desc = "Device Handlers are Missing or Not Published. Please verify the installation instructions and device handlers are present before continuing." + wikiObj = "#Installation_Instructions" + wikiDesc = "Device Installation (Wiki)" } else if(!preReqOk) { desc = "SmartThings Location is not returning (TimeZone: ${location?.timeZone}) or (ZipCode: ${location?.zipCode}) Please edit these settings under the ST IDE or Mobile App" @@ -167,12 +178,14 @@ def authPage() { desc = "Application Status has not received any messages to display" } if(stateSz > 80) { - desc += "${desc != "" ? "\n\n" : ""}Your Manager State Usage is Greater than 80% full. This is not normal and you should notify the developer." + desc += "${desc != "" ? "\n\n" : ""}Your Manager State Usage is Greater than 80% full. This is not normal and you should notify the developer." + settingUpdate("enDiagWebPage", "true", "bool") + href url: getAppEndpointUrl("diagHome"), style:"external", title:"NST Diagnostic Web Page", description:"Tap to view", required: true,state: "complete", image: getAppImg("web_icon.png") } LogAction("Status Message: $desc", "warn", true) - paragraph "$desc", required: true, state: null + paragraph title: title, "$desc", required: true, state: null if(showWiki) { - href url: getWikiPageUrl(), style:"embedded", required:false, title:"View the Projects Wiki", description:"Tap to open in browser", state: "complete", image: getAppImg("web_icon.png") + href url: getWikiPageUrl()+wikiObj, style:"embedded", required:false, title:wikiDesc, description:"Tap to open in browser", state: "complete", image: getAppImg("web_icon.png") } } devPageFooter("authErrLoadCnt", execTime) @@ -187,7 +200,7 @@ def authPage() { def result = ((atomicState?.appData?.updater?.setupVersion && !atomicState?.setupVersion) || (atomicState?.setupVersion?.toInteger() < atomicState?.appData?.updater?.setupVersion?.toInteger())) ? true : false if (result) { atomicState?.newSetupComplete = null } } - + if((settings.restStreamLocal == true) && (atomicState?.appData?.settings?.streaming.allowLocal != true)) { settingUpdate("restStreamLocal", "true", "bool") } def description def oauthTokenProvided = false @@ -203,7 +216,7 @@ def authPage() { LogAction("AuthToken not found: Directing to Login Page", "info", true) return dynamicPage(name: "authPage", title: "Login Page", nextPage: "mainPage", install: false, uninstall: false) { section("") { - paragraph appInfoDesc(), image: getAppImg("nst_manager_icon%402x.png", true) + paragraph appInfoDesc(), image: getAppImg("nst_manager_5%402x.png", true) } section(""){ paragraph "Tap 'Login to Nest' below to authorize SmartThings to your Nest Account.\n\nAfter login you will be taken to the 'Works with Nest' page. Read the info and if you 'Agree' press the 'Accept' button." @@ -213,6 +226,7 @@ def authPage() { devPageFooter("authLoadCnt", execTime) } } + else if(showChgLogOk()) { return changeLogPage() } else if(showDonationOk()) { return donationPage() } else { return mainPage() } @@ -225,18 +239,17 @@ def mainPage() { def setupComplete = (!atomicState?.newSetupComplete || !isInstalled) ? false : true return dynamicPage(name: "mainPage", title: "", nextPage: (!setupComplete ? "reviewSetupPage" : null), install: setupComplete, uninstall: false) { section("") { - href "changeLogPage", title: "", description: "${appInfoDesc()}", image: getAppImg("nst_manager_icon%402x.png", true) + href "changeLogPage", title: "", description: "${appInfoDesc()}", image: getAppImg("nst_manager_5%402x.png", true) if(settings?.restStreaming) { - def rStrEn = (atomicState?.appData?.eventStreaming?.enabled || getDevOpt() || betaMarker()) - href "pollPrefPage", title: "", state: ((atomicState?.restStreamingOn && rStrEn) ? "complete" : null), image: getAppImg("two_way_icon.png"), - description: "Nest Streaming: (${(!atomicState?.restStreamingOn || !rStrEn) ? "Inactive" : "Active"})" + Boolean strOn = atomicState?.restStreamingOn + href "pollPrefPage", title: "", state: (strOn ? "complete" : null), image: getAppImg("two_way_icon.png"), description: "Nest Streaming: (${!strOn ? "Inactive" : "Active"})" } if(atomicState?.appData && !appDevType()) { if(isAppUpdateAvail()) { href url: stIdeLink(), style:"external", required: false, title:"An Update is Available for ${appName()}!", - description:"Current: v${appVersion()} | New: ${atomicState?.appData?.updater?.versions?.app?.ver}\n\nTap to Open the IDE in Browser", state: "complete", image: getAppImg("update_icon.png") + description:"Current: v${appVersion()} | New: ${atomicState?.appData?.updater?.versions?.app?.ver}\n\nTap to Open the IDE in Browser", state: "complete", image: getAppImg("update_icon.png") } - if(atomicState?.clientBlacklisted) { + if(atomicState?.cltBlacklisted) { paragraph "This ID is blacklisted, please update software!\nIf software is up to date, contact developer", required: true, state: null } } @@ -244,12 +257,13 @@ def mainPage() { if(isInstalled) { if(settings?.structures && !atomicState?.structures) { atomicState.structures = settings?.structures } section("Devices & Location:") { - paragraph "Home/Away Status: (${strCapitalize(getLocationPresence())})", title: "Location: ${atomicState?.structName}", state: "complete", image: getAppImg("thermostat_icon.png") + paragraph "Home/Away Status: (${strCapitalize(getLocationPresence() ?: "Not Available Yet!")})", title: "Location: ${atomicState?.structName}", state: "complete", image: getAppImg("home_icon.png") def t1 = getDevicesDesc(false) def devDesc = t1 ? "${t1}\n\nTap to modify devices" : "Tap to configure" - href "deviceSelectPage", title: "Manage Devices", description: devDesc, state: "complete", image: "blank_icon.png" + href "deviceSelectPage", title: "Manage/View Devices", description: devDesc, state: "complete", image: "blank_icon.png" def devSelected = (atomicState?.structures && (atomicState?.thermostats || atomicState?.protects || atomicState?.cameras || atomicState?.presDevice || atomicState?.weatherDevice)) if(devSelected) { + href "devWebTiles", title: "View Device Tiles", description:"Tap to view", required: true,state: "complete", image: getAppImg("web_icon.png") href "devPrefPage", title: "Device Customization", description: "Tap to configure", image: getAppImg("device_pref_icon.png") } } @@ -258,18 +272,17 @@ def mainPage() { if(!isInstalled) { devicesPage() } - if(isInstalled && atomicState?.structures && (atomicState?.thermostats || atomicState?.protects || atomicState?.cameras)) { + if(isInstalled && atomicState?.structures && (atomicState?.thermostats || atomicState?.protects || atomicState?.cameras) && settings?.liteAppMode != true) { def t1 = getInstAutoTypesDesc() def autoDesc = t1 ? "${t1}\n\nTap to modify" : null section("Manage Automations:") { - href "automationsPage", title: "Automations", description: (autoDesc ? autoDesc : "Tap to configure"), state: (autoDesc ? "complete" : null), image: getAppImg("automation_icon.png") + href "automationsPage", title: "Automations", description: (autoDesc ? autoDesc : "Tap to configure"), state: (autoDesc ? "complete" : null), image: getAppImg("nst_automations_5.png") } } if(isInstalled) { section("Notifications Options:") { def t1 = getAppNotifConfDesc() - href "notifPrefPage", title: "Notifications", description: (t1 ? "${t1}\n\nTap to modify" : "Tap to configure"), state: (t1 ? "complete" : null), - image: getAppImg("notification_icon2.png") + href "notifPrefPage", title: "Notifications", description: (t1 ? "${t1}\n\nTap to modify" : "Tap to configure"), state: (t1 ? "complete" : null),image: getAppImg("notification_icon2.png") } section("Manage Polling, Logging, Nest Login, and More:") { def descStr = "" @@ -292,7 +305,9 @@ def mainPage() { section("Having Trouble?:") { href "helpPage", title: "Get Help | Diagnostics", description: "", image: getAppImg("help_ring_icon.png") if(settings?.enDiagWebPage) { - href url: getAppEndpointUrl("diagHome"), style:"external", title:"NST Diagnostic Web Page", description:"Tap to view", required: true,state: "complete", image: getAppImg("web_icon.png") + String diagTime = (getTimestampVal("remDiagLogActivatedDt") != null) ? "\n• Will Disable in:\n └ ${getDiagLogTimeRemaining()}" : "" + String diagStr = (settings?.enRemDiagLogging) ? "Diagnostic Logs: (ACTIVE)${diagTime}\n\nTap to view" : "Tap to view" + href url: getAppEndpointUrl("diagHome"), style:"external", title:"NST Diagnostic Web Page", description: diagStr, required: true, state: "complete", image: getAppImg("web_icon.png") } } section("Remove All Apps, Automations, and Devices:") { @@ -300,10 +315,91 @@ def mainPage() { } } atomicState.ok2InstallAutoFlag = false + // storageInfoSect() devPageFooter("mainLoadCnt", execTime) } } +// NEW STORAGE SmartApp +def storageInfoSect() { + //Integer stateSz = getStateSizePerc() + //if(!atomicState?.isInstalled || isAppLiteMode() || (stateSz < 50)) { return "" } + def storApp = getStorageApp(false) + section("Storage App Info:") { + if(storApp) { + def str = "" + str += "Version: V${storApp?.appVersion()}" + str += "\nUsage: ${storApp?.getStateSizePerc()}%" + paragraph str, state: "complete" + } else { + paragraph "Storage SmartApp Is Not Installed..." + } + } +} + +def getStorageVal(val) { + if(val) { + def storApp = getStorageApp() + def ret + if(storApp) { ret = storApp?.getStateVal(val as String) } // avoid multiple calls to child + return ret + } + return null +} + +def updStorageVal(sKey, sValue) { + if(sKey) { + def storApp = getStorageApp() + if(storApp) { return storApp?.stateUpdate(sKey as String, sValue) } + } +} + +def remStorageVal(String sKey) { + if(sKey) { + def storApp = getStorageApp() + if(storApp) { return storApp?.stateRemove(sKey as String) } + } +} + +def findStateStorageVal(String val) { + def storVal = getStorageVal(val) + def stateVal = atomicState?."$val" + if(storVal) { + if(stateVal) { state.remove(val) } + return storVal + } else if(stateVal) { return stateVal } + return null +} + +public storageAppInst(Boolean available) { + atomicState?.storageAppAvailable = (available == true) +} + +private getStorageApp(honorState = true) { + Integer stateSz = getStateSizePerc() + if(honorState && stateSz < 26) { return null } + if(honorState && isAppLiteMode()) { return null } + def storApp = getChildApps()?.find { it?.getAutomationType() == "storage" && it?.name == autoAppName() } + if(storApp) { + if(storApp?.label != getStorageAppChildLabel()) { storApp?.updateLabel(getStorageAppChildLabel()) } + storageAppInst(true) + return storApp + } else { + //runIn(5, "initStorageApp", [overwrite: true]) + storageAppInst(false) + return null + } +} + +private checkStorageApp() { + def oldStorApp = getChildApps()?.find{ it?.getAutomationType() == "storage" && it?.name != autoAppName() } + if(oldStorApp) { + LogAction("checkStorageApp | Removing Old Storage App", "warn", false) + deleteChildApp(oldStorApp) + updTimestampMap("lastAnalyticUpdDt", null) + } +} + def donationPage() { return dynamicPage(name: "donationPage", title: "", nextPage: "mainPage", install: false, uninstall: false) { section("") { @@ -348,29 +444,83 @@ def devicesPage() { } if (settings?.structures) { atomicState.structures = settings?.structures - def newStrucName = structs && structs?."${atomicState?.structures}" ? "${structs[atomicState?.structures]}" : null + def newStrucName = structs && structs?."${atomicState?.structures}" ? "${structs[atomicState?.structures]}" : null atomicState.structName = newStrucName ?: atomicState?.structName - //atomicState.structName = (settings?.structures && atomicState?.structures) ? "${structs[atomicState?.structures]}" : null + //atomicState.structName = (settings?.structures && atomicState?.structures) ? "${structs[atomicState?.structures]}" : null def stats = getNestThermostats() def statDesc = stats.size() ? "Found (${stats.size()}) Thermostats" : "No Thermostats" //LogAction("${statDesc} (${stats})", "info", false) + def str = "devicePage" + def dData = atomicState?.deviceData + + def t0 = [:] + t0 = dData?.thermostats?.findAll { it?.key?.toString() in settings?.thermostats } + def t1 = [] + t0?.each { devItem -> + LogAction("${str}: Found (${devItem?.value?.name})", "info", false) + if(devItem?.key && devItem?.value?.name) { + t1 << "${devItem.key.toString()}" + } + } + LogAction("${str} | Thermostats(${t0?.size()}): ${t1}", "info", true) + + def t3 = settings?.thermostats?.size() ?: 0 + if(t1?.size() != t3) { + LogAction("Thermostat Counts Wrong! | Current: (${t1?.size()}) | Expected: (${t3})", "error", true); + settingUpdate("thermostats", t1, "enum") + } + def coSmokes = getNestProtects() def coDesc = coSmokes.size() ? "Found (${coSmokes.size()}) Protects" : "No Protects" //LogAction("${coDesc} (${coSmokes})", "info", false) + t0 = [:] + t0 = dData?.smoke_co_alarms?.findAll { it?.key?.toString() in settings?.protects } + t1 = [] + t0?.each { devItem -> + LogAction("${str}: Found (${devItem?.value?.name})", "info", false) + if(devItem?.key && devItem?.value?.name) { + t1 << "${devItem.key.toString()}" + } + } + LogAction("${str} | Protects(${t0?.size()}): ${t1}", "info", true) + + t3 = settings?.protects?.size() ?: 0 + if(t1?.size() != t3) { + LogAction("Protects Counts Wrong! | Current: (${t1?.size()}) | Expected: (${t3})", "error", true); + settingUpdate("protects", t1, "enum") + } + def cams = getNestCameras() def camDesc = cams.size() ? "Found (${cams.size()}) Cameras" : "No Cameras" //LogAction("${camDesc} (${cams})", "info", false) + t0 = [:] + t0 = dData?.cameras?.findAll { it?.key?.toString() in settings?.cameras } + t1 = [] + t0?.each { devItem -> + LogAction("${str}: Found (${devItem?.value?.name})", "info", false) + if(devItem?.key && devItem?.value?.name) { + t1 << "${devItem.key.toString()}" + } + } + LogAction("${str} | Cameras(${t0?.size()}): ${t1}", "info", true) + + t3 = settings?.cameras?.size() ?: 0 + if(t1?.size() != t3) { + LogAction("Cameras Counts Wrong! | Current: (${t1?.size()}) | Expected: (${t3})", "error", true); + settingUpdate("cameras", t1, "enum") + } + section("Select Devices:") { if(!stats?.size() && !coSmokes.size() && !cams?.size()) { paragraph "No Devices were found" } if(stats?.size() > 0) { input(name: "thermostats", title:"Nest Thermostats", type: "enum", required: false, multiple: true, submitOnChange: true, metadata: [values:stats], image: getAppImg("thermostat_icon.png")) } - atomicState.thermostats = settings?.thermostats ? statState(settings?.thermostats) : null + atomicState.thermostats = settings?.thermostats ? statState(settings?.thermostats) : null if(coSmokes.size() > 0) { input(name: "protects", title:"Nest Protects", type: "enum", required: false, multiple: true, submitOnChange: true, metadata: [values:coSmokes], image: getAppImg("protect_icon.png")) @@ -387,6 +537,9 @@ def devicesPage() { atomicState.weatherDevice = settings?.weatherDevice ?: null } if(isInstalled) { + section("Device Web Tiles:") { + href "devWebTiles", title: "View Device Tiles", description:"Tap to view", required: true,state: "complete", image: getAppImg("web_icon.png") + } if(atomicState?.protects) { section("Nest Protect Alarm Simulation:") { def dt = atomicState?.isAlarmCoTestActiveDt @@ -397,6 +550,19 @@ def devicesPage() { } } +def devWebTiles() { + dynamicPage(name: "devWebTiles", title: "Device Tiles", uninstall: false) { + section("Device Web Tiles:") { + href url: getAppEndpointUrl("deviceTiles"), style:"external", title:"All Device Tiles\n(Take Longer to Load)", description:"Tap to view", required: true,state: "complete", image: getAppImg("view_icon.png") + if(atomicState?.thermostats) { href url: getAppEndpointUrl("tstatTiles"), style:"external", title:"Thermostat Tiles", description:"Tap to view", required: true,state: "complete", image: getAppImg("thermostat_icon.png") } + if(atomicState?.protects) { href url: getAppEndpointUrl("protectTiles"), style:"external", title:"Protect Tiles", description:"Tap to view", required: true,state: "complete", image: getAppImg("protect_icon.png") } + if(atomicState?.cameras) { href url: getAppEndpointUrl("cameraTiles"), style:"external", title:"Camera Tiles", description:"Tap to view", required: true,state: "complete", image: getAppImg("camera_icon.png") } + if(atomicState?.weatherDevice) { href url: getAppEndpointUrl("weatherTile"), style:"external", title:"Weather Tile", description:"Tap to view", required: true,state: "complete", image: getAppImg("weather_icon.png") } + } + } +} + + def devPrefPage() { def execTime = now() dynamicPage(name: "devPrefPage", title: "Device Options", uninstall: false) { @@ -409,17 +575,19 @@ def devPrefPage() { } if(atomicState?.cameras) { section("Camera Devices:") { - if(atomicState?.appData?.eventStreaming?.enabled == true || getDevOpt() || betaMarker()) { + // if(getDevOpt() || betaMarker()) { input "camTakeSnapOnEvt", "bool", title: "Take Snapshot on Motion Events?", required: false, defaultValue: true, submitOnChange: true, image: getAppImg("snapshot_icon.png") input "motionSndChgWaitVal", "enum", title: "Delay before Motion/Sound Events are marked Inactive?", required: false, defaultValue: 60, metadata: [values:waitValAltEnum(true)], submitOnChange: true, image: getAppImg("delay_time_icon.png") - // input "camEnMotionZoneFltr", "bool", title: "Allow filtering motion events by configured zones?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("motion_icon.png") - // if(settings?.camEnMotionZoneFltr) { - // href "camMotionZoneFltrPage", title: "Select the Zones for each camera to be used to trigger Motion?", description: "Tap to modify", image: getAppImg("zone_icon.png") - // } + input "camEnMotionZoneFltr", "bool", title: "Allow filtering motion events by configured zones?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("motion_icon.png") + if(settings?.camEnMotionZoneFltr) { + def camZones = getCamActivityZones() + def t0 = camMotionZoneDesc() + href "camMotionZoneFltrPage", title: "Restrict Motion to Certain Zones?", description: t0, params: [devices: atomicState?.cameras.sort{it?.value}, camZones: camZones], image: getAppImg("zone_icon.png"), state: (t0 ? "complete" : "") + } atomicState.needChildUpd = true - } else { - paragraph "No Camera Device Options Yet..." - } + // } else { + // paragraph "No Camera Device Options Yet..." + // } } } if(atomicState?.protects) { @@ -430,10 +598,8 @@ def devPrefPage() { } if(atomicState?.thermostats) { section("Thermostat Devices:") { - if(!inReview()) { - input ("tstatShowHistoryGraph", "bool", title: "Show Graph with Setpoint, Humidity, Temp History?", description: "This disables history collection", required: false, defaultValue: true, submitOnChange: true, - image: getAppImg("graph_icon2.png")) - } + input ("tstatShowHistoryGraph", "bool", title: "Show Graph with Setpoint, Humidity, Temp History?", description: "This disables history collection", required: false, defaultValue: true, submitOnChange: true, + image: getAppImg("graph_icon2.png")) input ("tempChgWaitVal", "enum", title: "Manual Temp Change Delay", required: false, defaultValue: 4, metadata: [values:waitValEnum()], submitOnChange: true, image: getAppImg("temp_icon.png")) atomicState.needChildUpd = true } @@ -457,46 +623,60 @@ def devPrefPage() { } } -def getCamActivityZones(devId) { - def actZones = atomicState?.deviceData?.cameras[devId]?.activity_zones +def getCamActivityZones() { def camZones = [:] - if(actZones.size()) { - actZones?.each { zn -> - def zId = zn?.id - def zName = zn?.name - def adni = [zId].join('.') - camZones[adni] = zName + atomicState?.cameras.sort{it?.value}.each { cam -> + camZones[cam?.key] = [:] + def actZones = atomicState?.deviceData?.cameras[cam?.key]?.activity_zones + if(actZones.size()) { + actZones?.each { zn -> + camZones[cam?.key][zn?.id as String] = zn?.name as String + } } } return camZones } -def camMotionZoneFltrPage() { +def camMotionZoneFltrPage(params) { + def cams = params?.devices + def camZones = params?.camZones + if(params?.devices && params?.camZones) { + atomicState.camFilterPageData = params + } else { + cams = atomicState?.camFilterPageData?.devices + camZones = atomicState?.camFilterPageData?.camZones + } def execTime = now() - dynamicPage(name: "camMotionZoneFltrPage", title: "", nextPage: "", install: false) { - def cnt = 1 - atomicState?.cameras.sort{it?.value}.each { cam -> - - def t0 = cam?.key - def t1 = cam?.value - def camZones = getCamActivityZones(t0) - def zoneDesc = camZones.size() ? "Found (${camZones.size()}) Zones" : "No Zones Found" - LogAction("${zoneDesc} (${camZones})", "info", true) - section("Camera: (${t1})") { - if(!camZones?.size()) { - paragraph "No Zones were found for this camera." - } else { - input(name: "${t0}_zones", title:"Available Zones", type: "enum", description: "${zoneDesc}", required: false, multiple: true, submitOnChange: true, - metadata: [values:camZones], image: getAppImg("zone_icon.png")) + dynamicPage(name: "camMotionZoneFltrPage", title: "", nextPage: "devPrefPage", install: false) { + if(cams && camZones) { + cams?.each { cm-> + def zones = camZones[cm?.key]?.sort { it?.value } + section("(${cm?.value}) Zones") { + if(!zones?.size()) { + paragraph "Camera has NO Zones..." + } else { + input("camera_${cm?.key}_zones", "enum", title:"Available Zones", description: "Found (${zones?.size()}) Zones", required: false, multiple: true, submitOnChange: true, options: zones, image: getAppImg("zone_icon.png")) + } } } - } - + } else { section() { paragraph "NO Camera Zones Found..." } } atomicState.needChildUpd = true devPageFooter("camZoneFltLoadCnt", execTime) } } +def camMotionZoneDesc() { + def desc = "" + if(atomicState?.cameras) { + atomicState?.cameras.sort{it?.value}.each { cam -> + if(settings?."camera_${cam?.key}_zones"?.size()) { + desc += "${desc == "" ? "" : "\n"}${cam?.value}: (${settings?."camera_${cam?.key}_zones"?.size()}) Zones" + } + } + } + return desc == "" ? null : desc +} + def custWeatherPage() { def execTime = now() dynamicPage(name: "custWeatherPage", title: "", nextPage: "", install: false) { @@ -506,6 +686,8 @@ def custWeatherPage() { input ("useCustWeatherLoc", "bool", title: "Use Custom Location?", description: "", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("info_icon2.png")) } if(settings?.useCustWeatherLoc) { +//ERS todo no more search +/* section("Select the Search method:") { input ("custWeatherLocSrch", "bool", title: "Use semi-automated search?", description: "", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("info_icon2.png")) } @@ -521,21 +703,28 @@ def custWeatherPage() { } } } else { +*/ section("Manually Enter a Location:") { +//ERS todo no more WU can set string... +/* href url:"https://www.wunderground.com/weatherstation/ListStations.asp", style:"embedded", required:false, title:"Weather Station ID Lookup", description: "Lookup Weather Station ID", image: getAppImg("search_icon.png") - input("custLocStr", "text", title: "Manaually Set Weather Location?", required: false, defaultValue: defZip, submitOnChange: true, image: getAppImg("weather_icon_grey.png")) - def validEnt = "\n\nWeather Stations: [pws:station_id]\nZipCodes: [90250]\nZWM: [zwm:zwm_number]" +*/ + input("custLocStr", "text", title: "Manually Set Weather Location?", required: false, defaultValue: defZip, submitOnChange: true, image: getAppImg("weather_icon_grey.png")) +//ERS todo no more PWS + //def validEnt = "\n\nWeather Stations: [pws:station_id]\nZipCodes: [90250]\nZWM: [zwm:zwm_number]" + def validEnt = "ZipCodes: [90250]" paragraph "Valid location entries are:${validEnt}", image: getAppImg("blank_icon.png") } - } +// } } - atomicState.lastWeatherUpdDt = 0 - atomicState?.lastForecastUpdDt = 0 + updTimestampMap("lastWeatherUpdDt", 0) + updTimestampMap("lastForecastUpdDt", 0) devPageFooter("custWeathLoadCnt", execTime) } } +/* def getWeatherQueryResults(query) { LogTrace("Getting Weather Query Results for '$query'") def objMap = [:] @@ -549,6 +738,32 @@ def getWeatherQueryResults(query) { } return objMap } +*/ + +def codeUpdatesPage(){ + dynamicPage(name: "codeUpdatesPage", uninstall: false, install: false) { + def theURL = "https://consigliere-regional.api.smartthings.com/?redirect=" + URLEncoder.encode(getAppEndpointUrl("stupdate")) + section() { + def desc = "\bSmartApps:" + desc += atomicState?.swVer?.mgrVer != null ? "${desc != "" ? "\n":""}Manager Version: (${atomicState?.swVer?.mgrVer})" : "" + desc += atomicState?.swVer?.autoSaVer != null ? "${desc != "" ? "\n":""}Automations Version: (${atomicState?.swVer?.autoSaVer})" : "" + desc += "\n\n\bDevices:" + desc += atomicState?.swVer?.tDevVer != null ? "${desc != "" ? "\n":""} • Thermostat Version: (${atomicState?.swVer?.tDevVer})" : "" + desc += atomicState?.swVer?.pDevVer != null ? "${desc != "" ? "\n":""} • Protect Version: (${atomicState?.swVer?.pDevVer})" : "" + desc += atomicState?.swVer?.camDevVer != null ? "${desc != "" ? "\n":""} • Camera Version: (${atomicState?.swVer?.camDevVer})" : "" + desc += atomicState?.swVer?.presDevVer != null ? "${desc != "" ? "\n":""} • Presence Version: (${atomicState?.swVer?.presDevVer})" : "" + desc += atomicState?.swVer?.weatDevVer != null ? "${desc != "" ? "\n":""} • Weather Version: (${atomicState?.swVer?.weatDevVer})" : "" + paragraph desc, state: "complete" + } + section() { + paragraph title: "What will this do?", "This process makes sure the following are up-to-date:\n • All SmartApps\n • All Devices\n\nAll you will need to do is sign in to the IDE and watch it go..." + href url: theURL, title: "Tap to Update", description: null, image: getAppImg("update_icon.png") + } + section("") { + href "changeLogPage", title: "View Change Log", description: "Tap to view", image: getAppImg("change_log_icon.png") + } + } +} def reviewSetupPage() { return dynamicPage(name: "reviewSetupPage", title: "Setup Review", install: true, uninstall: atomicState?.isInstalled) { @@ -573,10 +788,11 @@ def reviewSetupPage() { //getDevChgDesc() showVoiceRprtPrefs() - // section("App Mode: (Full or Lite)") { - // paragraph "Lite Mode will remove alot of the advanced features and allow for a very basic install. This will basically integrate Nest into ST without the bells and whistles." - // input ("liteAppMode", "bool", title: "Install the App in Lite Mode?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("app_analytics_icon.png")) - // } + section("App Mode: (Full or Lite)") { + def lmDesc = "Lite Mode will remove alot of the advanced features and allow for a very basic install. This will basically integrate Nest into ST without the bells and whistles." + input ("liteAppMode", "bool", title: "Lite App Mode?", description: lmDesc, required: false, defaultValue: false, submitOnChange: true, + image: getAppImg("app_analytics_icon.png")) + } section("Notifications:") { def t1 = getAppNotifConfDesc() href "notifPrefPage", title: "Notifications", description: (t1 ? "${t1}\n\nTap to modify" : "Tap to configure"), state: (t1 ? "complete" : null), image: getAppImg("notification_icon2.png") @@ -586,10 +802,8 @@ def reviewSetupPage() { href "pollPrefPage", title: "Device | Structure\nPolling Preferences", description: (pollDesc != "" ? "${pollDesc}\n\nTap to modify" : "Tap to configure"), state: (pollDesc != "" ? "complete" : null), image: getAppImg("timer_icon.png") } showDevSharePrefs() - if(atomicState?.showHelp) { - section("") { - href "infoPage", title: "Donations and Info", description: "Tap to view", image: getAppImg("info.png") - } + section("") { + href "infoPage", title: "Donations and Info", description: "Tap to view", image: getAppImg("info.png") } if(!atomicState?.isInstalled) { section("") { @@ -599,9 +813,13 @@ def reviewSetupPage() { } } +def isAppLiteMode() { + return (settings?.liteAppMode == true) +} + def showDevSharePrefs() { section("Share Data with Developer:") { - paragraph title: "What is this used for?", "These options send non-user identifiable information and error data to diagnose catch trending issues." + paragraph title: "What is this used for?", "These options send non-user identifiable information and error data to diagnose or catch trending issues." input ("optInAppAnalytics", "bool", title: "Send Install Data?", required: false, defaultValue: true, submitOnChange: true, image: getAppImg("app_analytics_icon.png")) input ("optInSendExceptions", "bool", title: "Send Error Data?", required: false, defaultValue: true, submitOnChange: true, image: getAppImg("diag_icon.png")) if(settings?.optInAppAnalytics != false) { @@ -618,14 +836,47 @@ def showDevSharePrefs() { def helpPage () { def execTime = now() dynamicPage(name: "helpPage", title: "Help and Diagnostics", install: false) { + section("App Info") { + paragraph "Current State Usage:\n${getStateSizePerc()}% (${getStateSize()} bytes)", required: true, state: (getStateSizePerc() <= 70 ? "complete" : null), + image: getAppImg("progress_bar.png") + if(atomicState?.isInstalled && atomicState?.structures && (atomicState?.thermostats || atomicState?.protects || atomicState?.cameras || atomicState?.weatherDevice)) { + input "enDiagWebPage", "bool", title: "Enable Diagnostic Web Page?", description: "", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("diagnostic_icon.png") + if(settings?.enDiagWebPage) { + href url: getAppEndpointUrl("diagHome"), style:"external", title:"NST Diagnostic Web Page", description:"Tap to view", required: true,state: "complete", image: getAppImg("web_icon.png") + } + } + } + if(getDevOpt()) { + settingUpdate("enDiagWebPage","true", "bool") + } + if(settings?.enDiagWebPage) { + section("How's Does Log Collection Work:", hideable: true, hidden: true) { + paragraph title: "How will the log collection work?", "When logs are enabled this SmartApp will create a child diagnostic app to store your logs which you can view under the diagnostics web page or share the url with the developer for remote troubleshooting.\n\n Turn off to remove the diag app and all data." + } + section("Log Collection:") { +/* + def formatVal = settings?.useMilitaryTime ? "MMM d, yyyy - HH:mm:ss" : "MMM d, yyyy - h:mm:ss a" + def tf = new SimpleDateFormat(formatVal) + if(getTimeZone()) { tf.setTimeZone(getTimeZone()) } +*/ + paragraph "Logging will automatically turn off in 48 hours and all logs will be purged." + input (name: "enRemDiagLogging", type: "bool", title: "Enable Log Collection?", required: false, defaultValue: (atomicState?.enRemDiagLogging ?: false), submitOnChange: true, image: getAppImg("log.png")) + if(atomicState?.enRemDiagLogging) { + def str = "Press Done/Save all the way back to the main smartapp page to allow the Diagnostic App to Install" + paragraph str, required: true, state: "complete" + } + } + } + diagLogProcChange((settings?.enDiagWebPage && settings?.enRemDiagLogging)) section("Help and Feedback:") { href url: getWikiPageUrl(), style:"embedded", required:false, title:"View the Projects Wiki", description:"Tap to open in browser", state: "complete", image: getAppImg("web_icon.png") href url: getIssuePageUrl(), style:"embedded", required:false, title:"Report | View Issues", description:"Tap to open in browser", state: "complete", image: getAppImg("issue_icon.png") href "feedbackPage", title: "Send Developer Feedback", description: "", image: getAppImg("feedback_icon.png") } - section("Diagnostic Data:") { - def t1 = getRemDiagDesc() - href "diagnosticPage", title: "View Diagnostic Info", description: (t1 ? "${t1 ?: ""}\n\nTap to view" : "Tap to view"), state: (t1) ? "complete" : null, image: getAppImg("diagnostic_icon.png") + section("SmartApp Security") { + paragraph title:"What does resetting do?", "If you share a url with someone and want to remove their access you can reset your token and this will invalidate any URL you shared and create a new one for you." + input (name: "resetSTAccessToken", type: "bool", title: "Reset SmartThings Access Token?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("reset_icon.png")) + resetSTAccessToken(settings?.resetSTAccessToken == true) } devPageFooter("helpLoadCnt", execTime) } @@ -635,7 +886,7 @@ def infoPage () { def execTime = now() dynamicPage(name: "infoPage", title: "Info and Instructions", install: false) { section("About this App:") { - paragraph appInfoDesc(), image: getAppImg("nst_manager_icon%402x.png", true) + paragraph appInfoDesc(), image: getAppImg("nst_manager_5%402x.png", true) } section("Donations:") { href url: textDonateLink(), style:"external", required: false, title:"Donations", @@ -685,6 +936,8 @@ def prefsPage() { section ("Misc. Options:") { input ("useMilitaryTime", "bool", title: "Use Military Time (HH:mm)?", defaultValue: false, submitOnChange: true, required: false, image: getAppImg("military_time_icon.png")) input ("disAppIcons", "bool", title: "Disable App Icons?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("no_icon.png")) + input ("liteAppMode", "bool", title: "Lite App Mode?", description: "Removes Automations", required: false, defaultValue: false, submitOnChange: true, + image: getAppImg("app_analytics_icon.png")) atomicState.needChildUpd = true } section("Customize Application Label:") { @@ -699,12 +952,12 @@ def voiceRprtPrefPage() { return dynamicPage(name: "voiceRprtPrefPage", title: "Voice Report Preferences", install: false, uninstall: false) { section("Report Customization:") { paragraph "These options allow you to configure how much info is included in the Thermostat voice reporting." - if(!atomicState?.appData?.reportPrefs?.disVoiceZoneRprt) { - input ("vRprtIncSchedInfo", "bool", title: "Include Automation Source Schedule Info?", required: false, defaultValue: true, submitOnChange: false, image: getAppImg("automation_icon.png")) + if(!atomicState?.appData?.settings?.reports?.disVoiceZoneRprt) { + input ("vRprtIncSchedInfo", "bool", title: "Include Automation Source Schedule Info?", required: false, defaultValue: true, submitOnChange: false, image: getAppImg("nst_automations_5.png")) input ("vRprtIncZoneInfo", "bool", title: "Include Current Zone Info?", required: false, defaultValue: true, submitOnChange: false, image: getAppImg("thermostat_icon.png")) input ("vRprtIncExtWeatInfo", "bool", title: "Include External Info?", required: false, defaultValue: true, submitOnChange: false, image: getAppImg("weather_icon.png")) } - if(!atomicState?.appData?.reportPrefs?.disVoiceUsageRprt) { + if(!atomicState?.appData?.settings?.reports?.disVoiceUsageRprt) { input ("vRprtIncUsageInfo", "bool", title: "Include Usage Info?", required: false, defaultValue: true, submitOnChange: false, image: getAppImg("usage_icon.png")) } } @@ -715,29 +968,36 @@ def voiceRprtPrefPage() { def pollPrefPage() { def execTime = now() dynamicPage(name: "pollPrefPage", title: "Polling Preferences", install: false) { - if(atomicState?.appData?.eventStreaming?.enabled == true || getDevOpt()) { - section("Rest Streaming (Experimental):") { - input(name: "restStreaming", title:"Enable Rest Streaming?", type: "bool", defaultValue: false, required: false, submitOnChange: true, image: getAppImg("two_way_icon.png")) - if(!settings?.restStreaming) { - paragraph title: "Streaming is an Experimental Feature", "It requires the install of our local NodeJS streaming service running on your home network. \n\n(This is a donation only feature)\nPlease send me a PM in the Community Forum if you have already donated and are interested" - } - } - if(settings?.restStreaming) { - section("Configure Streaming Service:") { - href "restSrvcDiscovery", title: "Auto-Discover Local Service", state: (settings?.selectedRestDevice ? "complete" : null), image: getAppImg("search_icon.png"), - description: selectedRestDiscSrvcDesc() ? "Selected Service:\n${selectedRestDiscSrvcDesc()}" : "Discover NST Service on your local network" - if(!settings?.selectedRestDevice) { - input(name: "restStreamIp", title:"Rest Service Address", type: "text", required: true, submitOnChange: true, image: getAppImg("ip_icon.png")) - input(name: "restStreamPort", title:"Rest Service Port", type: "number", defaultValue: 3000, required: true, submitOnChange: true, image: getAppImg("port_icon.png")) + section("Rest Streaming (Experimental):") { + input(name: "restStreaming", title:"Enable Rest Streaming?", type: "bool", defaultValue: false, required: false, submitOnChange: true, image: getAppImg("two_way_icon.png")) + if(!settings?.restStreaming) { + paragraph title: "Streaming is an Experimental Feature (Even though it's Stable)", "It requires the install of our local NodeJS streaming service running on your home network." + href url: streamLink(), style:"external", required: false, title:"Setup Instructions", description:"Tap to open in browser", state: "complete", image: getAppImg("web_icon.png") + } + } + if(settings?.restStreaming) { + section("Configure Streaming Service:") { + href "restSrvcDiscovery", title: "Auto-Discover Local Service", state: (settings?.selectedRestDevice ? "complete" : null), image: getAppImg("search_icon.png"), + description: selectedRestDiscSrvcDesc() ? "Selected Service:\n${selectedRestDiscSrvcDesc()}" : "Discover NST Service on your local network" + if(!settings?.selectedRestDevice) { + input(name: "restStreamIp", title:"Rest Service Address", type: "text", required: true, submitOnChange: true, image: getAppImg("ip_icon.png")) + input(name: "restStreamPort", title:"Rest Service Port", type: "number", defaultValue: 3000, required: true, submitOnChange: true, image: getAppImg("port_icon.png")) + } + if(atomicState?.appData?.settings?.streaming.allowLocal == true) { + input(name: "restStreamLocal", title:"Use Local Network to Send Events?", type: "bool", defaultValue: false, required: false, submitOnChange: true, image: getAppImg("two_way_icon.png")) + if(settings?.restStreamLocal == true) { + input(name: "restStreamLocalHub", type: "hub", title: "Select Local Hub", description: "This is the hub Stream events will be sent to.", submitOnChange: true, image: getAppImg("hub_icon.png")) + if(settings?.restStreamLocal && settings?.restStreamLocalHub) { subscribe(location, null, lanStreamEvtHandler, [filterEvents:false]) } } - getRestSrvcDesc() - paragraph title: "Notice", "This is still an experimental feature. It's subject to your local network and internet connections. If communication is lost the Manager will default back to standard polling." } - } else { - restDiscoveryClean() + getRestSrvcDesc() + paragraph title: "Notice", "This is still an experimental feature. It's subject to your local network and internet connections. If communication is lost the Manager will default back to standard polling." } - startStopStream() + } else { + restDiscoveryClean() } + startStopStream() + section("Polling:") { if(settings?.restStreaming && getRestHost()) { paragraph title: "NOTICE!", "These settings are only used when rest streaming is inactive or disabled", required: true, state: null, image: getAppImg("info_icon2.png") @@ -833,7 +1093,7 @@ def restSrvcDiscovery(params=[:]) { if(((discRfshCnt % 3) == 0) && ((discRfshCnt % 5) != 0)) { verifyDevices() } - //LogAction("options: $options devices: $devices objsFound $objsFound", "debug", true) + //LogAction("options: $options devices: $devices objsFound $objsFound", "debug", true) return dynamicPage(name:"restSrvcDiscovery", title:"", nextPage:"", refreshInterval:5) { section("Please wait while we discover your local NST Service devices. Discovery can take a couple minutes or more, so sit back and relax! Select your service below once discovered.") { @@ -932,34 +1192,34 @@ def automationsPage() { } } section("") { - app(name: "autoApp", appName: autoAppName(), namespace: "tonesto7", multiple: true, title: "Create New Automation (NST)", image: getAppImg("automation_icon.png")) + app(name: "autoApp", appName: autoAppName(), namespace: "tonesto7", multiple: true, title: "Create New Automation (NST)", image: getAppImg("nst_automations_5.png")) } if(autoAppInst) { section("Automation Details:") { - def schEn = getChildApps()?.findAll { (!(it.getAutomationType() in ["nMode", "watchDog", "remDiag"]) && it?.getActiveScheduleState()) } + def schEn = getChildApps()?.findAll { (!(it.getAutomationType() in ["nMode", "watchDog", "remDiag", "storage"]) && it?.getActiveScheduleState()) } if(schEn?.size()) { href "automationSchedulePage", title: "View Automation Schedule(s)", description: "", image: getAppImg("schedule_icon.png") } href "automationStatisticsPage", title: "View Automation Statistics", description: "", image: getAppImg("app_analytics_icon.png") } - section("Advanced Options: (Tap + to Show) ", hideable: true, hidden: true) { + section("Advanced Options: (Tap + to Show) ", hideable: true, hidden: true) { def descStr = "" descStr += (settings?.locDesiredCoolTemp || settings?.locDesiredHeatTemp) ? "Comfort Settings:" : "" - descStr += settings?.locDesiredHeatTemp ? "\n • Desired Heat Temp: (${settings?.locDesiredHeatTemp}°${getTemperatureScale()})" : "" - descStr += settings?.locDesiredCoolTemp ? "\n • Desired Cool Temp: (${settings?.locDesiredCoolTemp}°${getTemperatureScale()})" : "" + descStr += settings?.locDesiredHeatTemp ? "\n • Desired Heat Temp: (${settings?.locDesiredHeatTemp}${tUnitStr()})" : "" + descStr += settings?.locDesiredCoolTemp ? "\n • Desired Cool Temp: (${settings?.locDesiredCoolTemp}${tUnitStr()})" : "" descStr += (settings?.locDesiredComfortDewpointMax) ? "${(settings?.locDesiredCoolTemp || settings?.locDesiredHeatTemp) ? "\n\n" : ""}Dew Point:" : "" - descStr += settings?.locDesiredComfortDewpointMax ? "\n • Max Dew Point: (${settings?.locDesiredComfortDewpointMax}${getTemperatureScale()})" : "" + descStr += settings?.locDesiredComfortDewpointMax ? "\n • Max Dew Point: (${settings?.locDesiredComfortDewpointMax}${tUnitStr()})" : "" descStr += "${(settings?.locDesiredCoolTemp || settings?.locDesiredHeatTemp) ? "\n\n" : ""}${getSafetyValuesDesc()}" ?: "" def prefDesc = (descStr != "") ? "${descStr}\n\nTap to modify" : "Tap to configure" href "automationGlobalPrefsPage", title: "Global Automation Preferences", description: prefDesc, state: (descStr != "" ? "complete" : null), image: getAppImg("global_prefs_icon.png") input "disableAllAutomations", "bool", title: "Disable All Automations?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("disable_icon2.png") if(atomicState?.disableAllAutomations == false && settings?.disableAllAutomations) { - toggleAllAutomations(settings?.disableAllAutomations) + toggleAllAutomations(true) } else if (atomicState?.disableAllAutomations && !settings?.disableAllAutomations) { - toggleAllAutomations(settings?.disableAllAutomations) + toggleAllAutomations(true) } - atomicState?.disableAllAutomations = settings?.disableAllAutomations + atomicState?.disableAllAutomations = settings?.disableAllAutomations == true ? true : false //input "enTstatAutoSchedInfoReq", "bool", title: "Allow Other Smart Apps to Retrieve Thermostat automation Schedule info?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("info_icon2.png") href "automationKickStartPage", title: "Re-Initialize All Automations", description: "Tap to Update All Automations", image: getAppImg("reset_icon.png") } @@ -1044,13 +1304,23 @@ def automationStatisticsPage() { section(" ") { paragraph "${chld?.label}", state: "complete", image: getAutoIcon(autoType) def data = chld?.getAutomationStats() + def fmt = "M/d/yyyy - h:mm a" +/* def tf = new SimpleDateFormat("M/d/yyyy - h:mm a") tf.setTimeZone(getTimeZone()) - def lastModDt = data?.lastUpdatedDt ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastUpdatedDt.toString())) : null - def lastEvtDt = data?.lastEvent?.date ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastEvent?.date.toString())) : null - def lastActionDt = data?.lastActionData?.dt ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastActionData?.dt.toString())) : null - def lastEvalDt = data?.lastEvalDt ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastEvalDt.toString())) : null - def lastSchedDt = data?.lastSchedDt ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastSchedDt.toString())) : null + //def lastModDt = data?.lastUpdatedDt ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastUpdatedDt.toString())) : null + //def lastEvtDt = data?.lastEvent?.date ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastEvent?.date.toString())) : null + //def lastActionDt = data?.lastActionData?.dt ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastActionData?.dt.toString())) : null + //def lastEvalDt = data?.lastEvalDt ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastEvalDt.toString())) : null + //def lastSchedDt = data?.lastSchedDt ? tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", data?.lastSchedDt.toString())) : null +*/ + + def lastModDt = data?.lastUpdatedDt ? formatDt2(data?.lastUpdatedDt.toString(), fmt) : null + def lastEvtDt = data?.lastEvent?.date ? formatdt2(data?.lastEvent?.date.toString(), fmt) : null + def lastActionDt = data?.lastActionData?.dt ? formatDt2(data?.lastActionData?.dt.toString(), fmt) : null + def lastEvalDt = data?.lastEvalDt ? formatDt2(data?.lastEvalDt.toString(), fmt) : null + def lastSchedDt = data?.lastSchedDt ? formatDt2(data?.lastSchedDt.toString(), fmt) : null + def lastExecVal = data?.lastExecVal ?: null def execAvgVal = data?.execAvgVal ?: null @@ -1074,7 +1344,6 @@ def automationStatisticsPage() { paragraph "There is No Statistic Data to Display" } } - devPageFooter("viewAutoStatLoadCnt", execTime) } } @@ -1083,7 +1352,7 @@ def locDesiredClear() { LogTrace("locDesiredClear") def list = [ "locDesiredHeatTemp", "locDesiredCoolTemp","locDesiredComfortDewpointMax", "locDesiredTempScale", "locDesiredButton" ] list.each { item -> - settingUpdate(item.toString(), "") + settingRemove(item.toString()) } if(atomicState?.thermostats && settings?.clearLocDesired) { atomicState?.thermostats?.each { ts -> @@ -1091,24 +1360,24 @@ def locDesiredClear() { def canHeat = dev?.currentState("canHeat")?.stringValue == "false" ? false : true def canCool = dev?.currentState("canCool")?.stringValue == "false" ? false : true if(canHeat) { - settingUpdate("${dev?.deviceNetworkId}_safety_temp_min", "") + settingRemove("${dev?.deviceNetworkId}_safety_temp_min") } if(canCool) { - settingUpdate("${dev?.deviceNetworkId}_safety_temp_max", "") + settingRemove("${dev?.deviceNetworkId}_safety_temp_max") } if(settings?."${dev?.deviceNetworkId}_comfort_dewpoint_max") { - settingUpdate("${dev?.deviceNetworkId}_comfort_dewpoint_max", "") + settingRemove("${dev?.deviceNetworkId}_comfort_dewpoint_max") } if(settings?."${dev?.deviceNetworkId}_comfort_humidity_max") { - settingUpdate("${dev?.deviceNetworkId}_comfort_humidity_max", "") + settingRemove("${dev?.deviceNetworkId}_comfort_humidity_max") } } } - settingUpdate("clearLocDesired", false) + settingRemove("clearLocDesired") } def getGlobTitleStr(typ) { - return "Desired Default ${typ} Temp (°${getTemperatureScale()})" + return "Desired Default ${typ} Temp (${tUnitStr()})" } def automationGlobalPrefsPage() { @@ -1126,8 +1395,8 @@ def automationGlobalPrefsPage() { required: false, image: getAppImg("cool_icon.png") def tRange = (getTemperatureScale() == "C") ? "15..19" : "60..66" def wDev = getChildDevice(getNestWeatherId()) - def curDewPnt = wDev ? "${wDev?.currentDewpoint}°${getTemperatureScale()}" : 0 - input "locDesiredComfortDewpointMax", "decimal", title: "Default Dewpoint Threshold (${tRange} °${getTemperatureScale()})", required: false, range: trange, submitOnChange: true, + def curDewPnt = wDev ? "${wDev?.currentDewpoint}${tUnitStr()}" : 0 + input "locDesiredComfortDewpointMax", "decimal", title: "Default Dewpoint Threshold (${tRange} ${tUnitStr()})", required: false, range: trange, submitOnChange: true, image: getAppImg("dewpoint_icon.png") href url: "https://en.wikipedia.org/wiki/Dew_point#Relationship_to_human_comfort", style:"embedded", title: "What is Dew Point?", description:"Tap to view", image: getAppImg("instruct_icon.png") @@ -1158,15 +1427,15 @@ def automationGlobalPrefsPage() { def str = "" str += "Safety Values:" - str += safeTemp ? "\n• Safety Temps:\n └ Min: ${safeTemp.min}°${getTemperatureScale()}/Max: ${safeTemp.max}°${getTemperatureScale()}" : "\n• Safety Temps: (Not Set)" - str += dew_max ? "\n• Comfort Max Dewpoint:\n └ Max: ${dew_max}°${getTemperatureScale()}" : "\n• Comfort Max Dewpoint: (Not Set)" + str += safeTemp ? "\n• Safety Temps:\n └ Min: ${safeTemp.min}${tUnitStr()}/Max: ${safeTemp.max}${tUnitStr()}" : "\n• Safety Temps: (Not Set)" + str += dew_max ? "\n• Comfort Max Dewpoint:\n └ Max: ${dew_max}${tUnitStr()}" : "\n• Comfort Max Dewpoint: (Not Set)" paragraph "${str}", title:"${dev?.displayName}", state: "complete", image: getAppImg("instruct_icon.png") if(canHeat) { - input "${dev?.deviceNetworkId}_safety_temp_min", "decimal", title: "Low Safety Temp °(${getTemperatureScale()})", description: "Range within ${tempRangeValues()}", + input "${dev?.deviceNetworkId}_safety_temp_min", "decimal", title: "Low Safety Temp (${tUnitStr()})", description: "Range within ${tempRangeValues()}", range: tempRangeValues(), submitOnChange: true, required: false, image: getAppImg("heat_icon.png") } if(canCool) { - input "${dev?.deviceNetworkId}_safety_temp_max", "decimal", title: "High Safety Temp °(${getTemperatureScale()})", description: "Range within ${tempRangeValues()}", + input "${dev?.deviceNetworkId}_safety_temp_max", "decimal", title: "High Safety Temp (${tUnitStr()})", description: "Range within ${tempRangeValues()}", range: tempRangeValues(), submitOnChange: true, required: false, image: getAppImg("cool_icon.png") } def tmin = settings?."${dev?.deviceNetworkId}_safety_temp_min" @@ -1182,7 +1451,7 @@ def automationGlobalPrefsPage() { atomicState?."${dev?.deviceNetworkId}_safety_temp_max" = tmax def tRange = (getTemperatureScale() == "C") ? "15..19" : "60..66" - input "${dev?.deviceNetworkId}_comfort_dewpoint_max", "decimal", title: "Dewpoint Threshold (${tRange} °${getTemperatureScale()})", required: false, range: trange, + input "${dev?.deviceNetworkId}_comfort_dewpoint_max", "decimal", title: "Dewpoint Threshold (${tRange} ${tUnitStr()})", required: false, range: trange, submitOnChange: true, image: getAppImg("dewpoint_icon.png") // def hrange = "10..80" // input "${dev?.deviceNetworkId}_comfort_humidity_max", "number", title: "Max. Humidity Desired (%)", description: "Range within ${hrange}", range: hrange, @@ -1221,36 +1490,50 @@ def automationKickStartPage() { def notifPrefPage() { def execTime = now() dynamicPage(name: "notifPrefPage", install: false) { - def sectDesc = !location.contactBookEnabled ? "Enable push notifications below" : "Select People or Devices to Receive Notifications" - section(sectDesc) { - if(!location.contactBookEnabled) { - input(name: "usePush", type: "bool", title: "Send Push Notitifications", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("notification_icon.png")) - } else { - input(name: "recipients", type: "contact", title: "Select Default Contacts", required: false, submitOnChange: true, image: getAppImg("recipient_icon.png")) { - input ("phone", "phone", title: "Phone Number to send SMS to", required: false, submitOnChange: true, image: getAppImg("notification_icon2.png")) - } + section("Enable Text Messaging:") { + input "phone", "phone", title: "Send SMS to Number\n(Optional)", required: false, submitOnChange: true, image: getAppImg("notification_icon2.png") + } + section("Enable Push Messages:") { + input "usePush", "bool", title: "Send Push Notifications\n(Optional)", required: false, submitOnChange: true, defaultValue: false, image: getAppImg("notification_icon.png") + } + section("Enable Pushover Support:") { + input ("pushoverEnabled", "bool", title: "Use Pushover Integration", required: false, submitOnChange: true, image: getAppImg("pushover_icon.png")) + if(settings?.pushoverEnabled == true) { + if(atomicState?.isInstalled) { + if(!atomicState?.pushoverManager) { + paragraph "If this is the first time enabling Pushover than leave this page and come back if the devices list is empty" + pushover_init() + } else { + input "pushoverDevices", "enum", title: "Select Pushover Devices", description: "Tap to select", groupedOptions: getPushoverDevices(), multiple: true, required: false, submitOnChange: true + if(settings?.pushoverDevices) { + def t0 = [(-2):"Lowest", (-1):"Low", 0:"Normal", 1:"High", 2:"Emergency"] + input "pushoverPriority", "enum", title: "Notification Priority (Optional)", description: "Tap to select", defaultValue: 0, required: false, multiple: false, submitOnChange: true, options: t0 + input "pushoverSound", "enum", title: "Notification Sound (Optional)", description: "Tap to select", defaultValue: "pushover", required: false, multiple: false, submitOnChange: true, options: getPushoverSounds() + } + } + } else { paragraph "New Install Detected!!!\n\n1. Press Done to Finish the Install.\n2. Goto the Automations Tab at the Bottom\n3. Tap on the SmartApps Tab above\n4. Select ${app?.getLabel()} and Resume configuration", state: "complete" } } - if(settings?.recipients || settings?.phone || settings?.usePush) { + } + if(settings?.phone || settings?.usePush || (settings?.pushoverEnabled && settings?.pushoverDevices)) { + section("Notification Restrictions:") { def t1 = getNotifSchedDesc() href "setNotificationTimePage", title: "Notification Restrictions", description: (t1 ?: "Tap to configure"), state: (t1 ? "complete" : null), image: getAppImg("restriction_icon.png") } - } - if(settings?.recipients || settings?.phone || settings?.usePush) { - if(settings?.recipients && !atomicState?.pushTested) { - if(sendMsg("Info", "Push Notification Test Successful. Notifications Enabled for ${appName()}", false)) { + if((settings?.usePush || (settings?.pushoverEnabled && settings?.pushoverDevices)) && !atomicState?.pushTested && atomicState?.pushoverManager) { + if(sendMsg("Info", "Push Notification Test Successful. Notifications Enabled for ${appName()}", true)) { atomicState.pushTested = true } } - section("Location Notifications:") { + section("Location Alerts:") { paragraph "Get notified when the Location changes from Home/Away", state: "complete" input name: "locPresChangeMsg", type: "bool", title: "Notify on Home/Away changes?", defaultValue: true, submitOnChange: true, image: getAppImg("presence_icon.png") } - section("Alert Configurations:") { + section("Other Alerts:") { def t1 = getAppNotifDesc() def appDesc = t1 ? "${t1}\n\n" : "" href "notifConfigPage", title: "App Notifications", description: "${appDesc}Tap to configure", params: [pType:"app"], state: (appDesc != "" ? "complete" : null), - image: getAppImg("nst_manager_icon.png") + image: getAppImg("nst_manager_5.png") t1 = getDevNotifDesc() def devDesc = t1 ? "${t1}\n\n" : "" href "notifConfigPage", title: "Device Notifications", description: "${devDesc}Tap to configure", params: [pType:"dev"], state: (devDesc != "" ? "complete" : null), @@ -1258,8 +1541,8 @@ def notifPrefPage() { t1 = getAutoNotifDesc() def autoDesc = t1 ? "${t1}\n\n" : "" href "notifConfigPage", title: "Automation Notifications", description: "${autoDesc}Tap to configure", params: [pType:"auto"], state: (autoDesc != "" ? "complete" : null), - image: getAppImg("automation_icon.png") - if(atomicState?.appData?.aaPrefs?.enAaMsgQueue == true) { + image: getAppImg("nst_automations_5.png") + if(atomicState?.appData?.settings?.askAlexa?.enAaMsgQueue == true) { t1 = getAskAlexaDesc() def aaDesc = t1 ? "${t1}\n\n" : "" href "notifConfigPage", title: "AskAlexa Integration", description: "${aaDesc}Tap to configure", params: [pType:"askAlexa"], state: (aaDesc != "" ? "complete" : null), @@ -1378,35 +1661,37 @@ def notifConfigPage(params) { def getAppNotifDesc() { def str = "" - str += settings?.appApiIssuesMsg != false && settings?.appApiFailedCmdMsg != false ? "\n• API CMD Failures: (${strCapitalize(settings?.appApiFailedCmdMsg ?: "True")})" : "" - str += settings?.appApiIssuesMsg != false && settings?.appApiRateLimitMsg != false ? "\n• API Rate-Limiting: (${strCapitalize(settings?.appApiRateLimitMsg ?: "True")})" : "" - str += settings?.sendMissedPollMsg != false ? "\n• Missed Poll Alerts: (${strCapitalize(settings?.sendMissedPollMsg ?: "True")})" : "" - str += settings?.appDbgDiagRemindMsg != false ? "\n• Debug Log Reminder: (${strCapitalize(settings?.appDbgDiagRemindMsg ?: "True")})" : "" - str += settings?.sendAppUpdateMsg != false ? "\n• Code Updates: (${strCapitalize(settings?.sendAppUpdateMsg ?: "True")})" : "" + str += settings?.appApiIssuesMsg != false && settings?.appApiFailedCmdMsg != false ? "${str != "" ? "\n" : ""} • API CMD Failures: (${strCapitalize(settings?.appApiFailedCmdMsg ?: "True")})" : "" + str += settings?.appApiIssuesMsg != false && settings?.appApiRateLimitMsg != false ? "${str != "" ? "\n" : ""} • API Rate-Limiting: (${strCapitalize(settings?.appApiRateLimitMsg ?: "True")})" : "" + str += settings?.sendMissedPollMsg != false ? "${str != "" ? "\n" : ""} • Missed Poll Alerts: (${strCapitalize(settings?.sendMissedPollMsg ?: "True")})" : "" + str += settings?.appDbgDiagRemindMsg != false ? "${str != "" ? "\n" : ""} • Debug Log Reminder: (${strCapitalize(settings?.appDbgDiagRemindMsg ?: "True")})" : "" + str += settings?.sendAppUpdateMsg != false ? "${str != "" ? "\n" : ""} • Code Updates: (${strCapitalize(settings?.sendAppUpdateMsg ?: "True")})" : "" return str != "" ? str : null } def getDevNotifDesc() { def str = "" - str += settings?.devHealthNotifyMsg != false ? "\n• Health Alerts: (${strCapitalize(settings?.devHealthNotifyMsg ?: "True")})" : "" - str += settings?.camStreamNotifMsg != false ? "\n• Camera Stream Alerts: (${strCapitalize(settings?.camStreamNotifMsg ?: "True")})" : "" - str += settings?.weathAlertNotif != false ? "\n• Weather Alerts: (${strCapitalize(settings?.weathAlertNotif ?: "True")})" : "" + str += settings?.devHealthNotifyMsg != false ? "${str != "" ? "\n" : ""} • Health Alerts: (${strCapitalize(settings?.devHealthNotifyMsg ?: "True")})" : "" + str += settings?.camStreamNotifMsg != false ? "${str != "" ? "\n" : ""} • Camera Stream Alerts: (${strCapitalize(settings?.camStreamNotifMsg ?: "True")})" : "" + str += settings?.weathAlertNotif != false ? "${str != "" ? "\n" : ""} • Weather Alerts: (${strCapitalize(settings?.weathAlertNotif ?: "True")})" : "" return str != "" ? str : null } def getAutoNotifDesc() { def str = "" - str += settings?.watchDogNotifMissedEco ? "\n• WatchDog Eco Alerts: (${strCapitalize(settings?.watchDogNotifMissedEco)})" : "" + str += settings?.watchDogNotifMissedEco ? "${str != "" ? "\n" : ""} • WatchDog Eco Alerts: (${strCapitalize(settings?.watchDogNotifMissedEco)})" : "" return str != "" ? str : null } def getAskAlexaDesc() { def str = "" - str += settings?.allowAskAlexaMQ ? "\n• Ask Alexa Msg Queue: (${strCapitalize(settings?.allowAskAlexaMQ)})" : "" - str += getAskAlexaMultiQueueEn() && atomicState?.askAlexaMQList ? "\nMultiple Queues Available:\n• Queues: (${atomicState?.askAlexaMQList?.size()})" : "" + str += settings?.allowAskAlexaMQ ? "${str != "" ? "\n" : ""} • Ask Alexa Msg Queue: (${strCapitalize(settings?.allowAskAlexaMQ)})" : "" + str += getAskAlexaMultiQueueEn() && atomicState?.askAlexaMQList ? "${str != "" ? "\n" : ""}Multiple Queues Available:\n• Queues: (${atomicState?.askAlexaMQList?.size()})" : "" return str != "" ? str : null } +def addNewline(str) { return "${str != "" ? "\n" : ""}${str}"} + def getAppNotifConfDesc() { def str = "" if(pushStatus()) { @@ -1414,14 +1699,16 @@ def getAppNotifConfDesc() { def de = getDevNotifDesc() def au = getAutoNotifDesc() def nd = getNotifSchedDesc() - str += (settings?.recipients) ? "Sending via Contact Book (True)" : "" - str += (settings?.usePush) ? "Sending via Push: (True)" : "" - str += (settings?.phone) ? "\nSending via SMS: (True)" : "" - str += (ap || de || au) ? "\nEnabled Alerts:" : "" - str += (ap) ? "\n• App Alerts (True)" : "" - str += (de) ? "\n• Device Alerts (True)" : "" - str += (au) ? "\n• Automation Alerts (True)" : "" - str += (nd) ? "\n\nAlert Restrictions:\n${nd}" : "" + str += (settings?.usePush) ? "${str != "" ? "\n" : ""}Sending via: (Push)" : "" + str += (settings?.pushoverEnabled) ? "${str != "" ? "\n" : ""}Pushover: (Enabled)" : "" + str += (settings?.pushoverEnabled && settings?.pushoverPriority) ? "${str != "" ? "\n" : ""} • Priority: (${settings?.pushoverPriority})" : "" + str += (settings?.pushoverEnabled && settings?.pushoverSound) ? "${str != "" ? "\n" : ""} • Sound: (${settings?.pushoverSound})" : "" + str += (settings?.phone) ? "${str != "" ? "\n" : ""}Sending via: (SMS)" : "" + str += (ap || de || au) ? "${str != "" ? "\n" : ""}\nEnabled Alerts:" : "" + str += (ap) ? "${str != "" ? "\n" : ""} • App Alerts (True)" : "" + str += (de) ? "${str != "" ? "\n" : ""} • Device Alerts (True)" : "" + str += (au) ? "${str != "" ? "\n" : ""} • Automation Alerts (True)" : "" + str += (nd) ? "${str != "" ? "\n" : ""}\nAlert Restrictions:\n${nd}" : "" } return str != "" ? str : null } @@ -1456,11 +1743,14 @@ def buildNotifPrefMap() { return res } -def toggleAllAutomations(disable=false) { - def dis = disable == null ? false : disable +def toggleAllAutomations(upd = false) { + def t0 = settings?.disableAllAutomations == true ? true : false + atomicState?.disableAllAutomations = t0 + def disStr = !t0 ? "Returning control to" : "Disabling" def cApps = getChildApps() cApps.each { ca -> - ca?.setAutomationStatus(dis, true) + LogAction("toggleAllAutomations: ${disStr} automation ${ca?.label}", "info", true) + ca?.setAutomationStatus(upd) } } @@ -1605,7 +1895,7 @@ def debugPrefPage() { section ("Application Logs") { input ("debugAppendAppName", "bool", title: "Show App/Device Name on all Log Entries?", required: false, defaultValue: true, submitOnChange: true, image: getAppImg("log.png")) input (name: "appDebug", type: "bool", title: "Show ${appName()} Logs in the IDE?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("log.png")) - if(appDebug) { + if(settings?.appDebug) { input (name: "advAppDebug", type: "bool", title: "Show Verbose Logs?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("list_icon.png")) } else { settingUpdate("advAppDebug", "false", "bool") @@ -1617,7 +1907,7 @@ def debugPrefPage() { } section("Diagnostics:") { def t1 = getRemDiagDesc() - href "diagnosticPage", title: "View Diagnostic Info", description: (t1 ? "${t1 ?: ""}\n\nTap to view" : "Tap to view"), state: (t1) ? "complete" : null, image: getAppImg("diagnostic_icon.png") + href "helpPage", title: "View Diagnostic Info", description: (t1 ? "${t1 ?: ""}\n\nTap to view" : "Tap to view"), state: (t1) ? "complete" : null, image: getAppImg("diagnostic_icon.png") } section ("Reset Application Data") { input (name: "resetAllData", type: "bool", title: "Reset Application Data?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("reset_icon.png")) @@ -1625,96 +1915,52 @@ def debugPrefPage() { else { LogAction("Reset Application Data Disabled", "info", true) } } if(settings?.appDebug || settings?.childDebug) { - if(atomicState?.debugEnableDt == null) { atomicState?.debugEnableDt = getDtNow() } - } else { atomicState?.debugEnableDt = null } + if(getTimestampVal("debugEnableDt") == null) { updTimestampMap("debugEnableDt", getDtNow()) } + } else { updTimestampMap("debugEnableDt", null) } atomicState.needChildUpd = true devPageFooter("logPrefLoadCnt", execTime) } } -def diagnosticPage () { - def execTime = now() - dynamicPage(name: "diagnosticPage", title: "Diagnostics Page", install: false) { - section("App Info") { - paragraph "Current State Usage:\n${getStateSizePerc()}% (${getStateSize()} bytes)", required: true, state: (getStateSizePerc() <= 70 ? "complete" : null), - image: getAppImg("progress_bar.png") - if(atomicState?.isInstalled && atomicState?.structures && (atomicState?.thermostats || atomicState?.protects || atomicState?.cameras || atomicState?.weatherDevice)) { - input "enDiagWebPage", "bool", title: "Enable Diagnostic Web Page?", description: "", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("diagnostic_icon.png") - if(settings?.enDiagWebPage) { - href url: getAppEndpointUrl("diagHome"), style:"external", title:"NST Diagnostic Web Page", description:"Tap to view", required: true,state: "complete", image: getAppImg("web_icon.png") - } - } - } - if(getDevOpt()) { - settingUpdate("enDiagWebPage","true", "bool") - } - if(settings?.enDiagWebPage) { - section("Log Collection:") { - def formatVal = settings?.useMilitaryTime ? "MMM d, yyyy - HH:mm:ss" : "MMM d, yyyy - h:mm:ss a" - def tf = new SimpleDateFormat(formatVal) - if(getTimeZone()) { tf.setTimeZone(getTimeZone()) } - paragraph title: "How will the log collection work?", "Once enabled this SmartApp will create a child app to store your logs in this diagnostic app and you can view the page or share the url with the developer. Turn off to remove the diag app and all data." - paragraph "This will automatically turn off 48 hours" - input (name: "enRemDiagLogging", type: "bool", title: "Enable Log Collection?", required: false, defaultValue: (atomicState?.enRemDiagLogging ?: false), submitOnChange: true, image: getAppImg("log.png")) - if(atomicState?.enRemDiagLogging) { - def str = "Press Done/Save all the way back to the main smartapp page to allow the Diagnostic App to Install" - paragraph str, required: true, state: "complete" - } - } - } - diagLogProcChange((settings?.enDiagWebPage && settings?.enRemDiagLogging)) - - section("SmartApp Security") { - paragraph title:"What does resetting do?", "If you share a url with someone and want to remove their access you can reset your token and this will invalidate any URL you shared and create a new one for you." - input (name: "resetSTAccessToken", type: "bool", title: "Reset SmartThings Access Token?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("reset_icon.png")) - if(settings?.resetSTAccessToken) { resetSTAccessToken() } - } - - devPageFooter("diagLoadCnt", execTime) - } -} - def getRemDiagApp() { - def remDiagApp = null - def cApps = getChildApps() - cApps?.each { ca -> - if(ca?.getAutoType() == "remDiag") { - remDiagApp = ca - } + def remDiagApp = getChildApps()?.find { it?.getAutomationType() == "remDiag" && it?.name == autoAppName() } + if(remDiagApp) { + if(remDiagApp?.label != getRemDiagAppChildLabel()) { remDiagApp?.updateLabel(getRemDiagAppChildLabel()) } + return remDiagApp + } else { + return null } - return remDiagApp } -void diagLogProcChange(setOn) { - def diagAllowed = atomicState?.appData?.database?.allowRemoteDiag == true ? true : false - //log.debug "diagAllowed: $diagAllowed" +private diagLogProcChange(setOn) { + // log.trace "diagLogProcChange($setOn)" def doInit = false def msg = "Remote Diagnostic Logs " - if(diagAllowed && setOn) { - if(!atomicState?.enRemDiagLogging && atomicState?.remDiagLogActivatedDt == null) { + if(setOn) { + if(!atomicState?.enRemDiagLogging && getTimestampVal("remDiagLogActivatedDt") == null) { msg += "activated" doInit = true } } else { - if(atomicState?.remDiagLogActivatedDt != null) { + if(getTimestampVal("remDiagLogActivatedDt") != null || atomicState?.enRemDiagLogging) { msg += "deactivated" settingUpdate("enRemDiagLogging", "false","bool") atomicState?.enRemDiagLogging = false - atomicState?.remDiagLogActivatedDt = null // require toggle off then on again to force back on after timeout + updTimestampMap("remDiagLogActivatedDt", null) doInit = true } } if(doInit) { - def kdata = getState()?.findAll { (it?.key in ["remDiagLogDataStore", "remDiagDataSentDt" ]) } + def kdata = getState()?.findAll { (it?.key in ["remDiagLogDataStore" /* , "remDiagDataSentDt"*/ ]) } kdata.each { kitem -> state.remove(kitem?.key.toString()) } - if(diagAllowed && setOn) { - atomicState?.remDiagDataSentDt = getDtNow() // allow us some time for child to start - atomicState?.enRemDiagLogging = true - atomicState?.remDiagLogActivatedDt = getDtNow() - } + updTimestampMap("remDiagDataSentDt", getDtNow()) // allow us some time for child to start + //atomicState?.remDiagDataSentDt = getDtNow() // allow us some time for child to start + atomicState?.enRemDiagLogging = true + updTimestampMap("remDiagLogActivatedDt", getDtNow()) + initRemDiagApp() LogAction(msg, "info", true) if(!atomicState?.enRemDiagLogging) { //when turning off, tell automations; turn on - user does done @@ -1726,25 +1972,14 @@ void diagLogProcChange(setOn) { } } atomicState.forceChildUpd = true - atomicState?.lastAnalyticUpdDt = null // will force def autoDesc = getInstAutoTypesDesc() // This is a hack to get installedAutomations data updated without waiting for user to hit done + updTimestampMap("lastAnalyticUpdDt", null) } } -/* -def genRandId(int length){ - String alphabet = new String("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") - int n = alphabet.length() - String result = new String() - Random r = new Random() - for (int i=0; i ctr) ? "\n\n" : "" ctr = (str != "") ? ctr += 1 : ctr siz = (str == "") ? siz -= 1 : siz @@ -1848,7 +2074,7 @@ def getSafetyValuesDesc() { } def showVoiceRprtPrefs() { - if(atomicState?.thermostats && (!atomicState?.appData?.reportPrefs?.disVoiceZoneRprt || !atomicState?.appData?.reportPrefs?.disVoiceUsageRprt)) { + if(atomicState?.thermostats && (!atomicState?.appData?.settings?.reports?.disVoiceZoneRprt || !atomicState?.appData?.settings?.reports?.disVoiceUsageRprt)) { def rPrefs = getVoiceRprtPrefDesc() section("Voice Reports:") { href "voiceRprtPrefPage", title: "Voice Report Preferences", description: (rPrefs ? "${rPrefs}\n\nTap to modify" : "Tap to configure"), state: (rPrefs ? "complete" : ""), image: getAppImg("speech2_icon.png") @@ -1858,8 +2084,8 @@ def showVoiceRprtPrefs() { def getVoiceRprtPrefs() { return [ - "allowVoiceUsageRprt":(atomicState?.appData?.reportPrefs?.disVoiceUsageRprt == true) ? false : true, - "allowVoiceZoneRprt":(atomicState?.appData?.reportPrefs?.disVoiceZoneRprt == true) ? false : true, + "allowVoiceUsageRprt":(atomicState?.appData?.settings?.reports?.disVoiceUsageRprt == true) ? false : true, + "allowVoiceZoneRprt":(atomicState?.appData?.settings?.reports?.disVoiceZoneRprt == true) ? false : true, "vRprtSched":(settings?.vRprtIncSchedInfo == false ? false : true), "vRprtZone":(settings?.vRprtIncZoneInfo == false ? false : true), "vRprtExtWeat":(settings?.vRprtIncExtWeatInfo == false ? false : true), @@ -1879,13 +2105,12 @@ def getVoiceRprtPrefDesc() { } def getPollingConfDesc() { - def rStrEn = (atomicState?.appData?.eventStreaming?.enabled || getDevOpt() || betaMarker()) def pollValDesc = (!settings?.pollValue || settings?.pollValue == "180") ? "" : (!atomicState?.streamPolling ? " (Custom)" : " (Stream)") def pollStrValDesc = (!settings?.pollStrValue || settings?.pollStrValue == "180") ? "" : (!atomicState?.streamPolling ? " (Custom)" : " (Stream)") def pollWeatherValDesc = (!settings?.pollWeatherValue || settings?.pollWeatherValue == "900") ? "" : " (Custom)" def pollWaitValDesc = (!settings?.pollWaitVal || settings?.pollWaitVal == "10") ? "" : " (Custom)" def pStr = "" - pStr += rStrEn ? "Nest Stream: (${(settings.restStreaming && rStrEn) ? "${(!atomicState?.restStreamingOn) ? "Not Active" : "Active"}" : "Off"})" : "" + pStr += "Nest Stream: (${settings.restStreaming ? (!atomicState?.restStreamingOn ? "Not Active" : "Active") : "Off"})" pStr += "\nPolling: (${!atomicState?.pollingOn ? "Not Active" : "Active"})" pStr += "\n• Device: (${getInputEnumLabel((!atomicState?.streamPolling ? (pollValue ?: 180) : 300), pollValEnum(true))}) ${pollValDesc}" pStr += "\n• Structure: (${getInputEnumLabel((!atomicState?.streamPolling ? (pollStrValue?:180) : 300), pollValEnum())}) ${pollStrValDesc}" @@ -1897,7 +2122,6 @@ def getPollingConfDesc() { // Parent only method def getNotifSchedDesc() { def sun = getSunriseAndSunset() - //def schedInverted = settings?.DmtInvert def startInput = settings?.qStartInput def startTime = settings?.qStartTime def stopInput = settings?.qStopInput @@ -1915,7 +2139,6 @@ def getNotifSchedDesc() { return (notifDesc != "") ? "${notifDesc}" : null } - def getWeatherConfDesc() { def str = "" def defZip = getStZipCode() ? getStZipCode() : getNestZipCode() @@ -1926,12 +2149,15 @@ def getWeatherConfDesc() { def getCustWeatherLoc(desc=false) { def res = null if(settings?.useCustWeatherLoc) { +/* if(settings?.custWeatherLocSrch == true) { if(settings?.custWeatherResultItems != null) { res = desc ? (settings?.custWeatherResultItems[0]?.split("\\:"))[1].split("\\.")[0] : settings?.custWeatherResultItems[0].toString() } - } else if(settings?.custLocStr != null) { - res = settings?.custLocStr + } else +*/ + if(settings?.custLocStr != null) { + res = settings?.custLocStr.toString() } } return res @@ -1981,7 +2207,7 @@ def getRemDiagDesc() { } /****************************************************************************** -* NEST LOGIN PAGES * +* NEST LOGIN PAGES * *******************************************************************************/ def nestLoginPrefPage () { if(!atomicState?.authToken) { @@ -1989,13 +2215,13 @@ def nestLoginPrefPage () { } else { def execTime = now() return dynamicPage(name: "nestLoginPrefPage", nextPage: atomicState?.authToken ? "" : "authPage", install: false) { - def formatVal = settings?.useMilitaryTime ? "MMM d, yyyy - HH:mm:ss" : "MMM d, yyyy - h:mm:ss a" - def tf = new SimpleDateFormat(formatVal) - if(getTimeZone()) { tf.setTimeZone(getTimeZone()) } - atomicState.authTokenCreatedDt = atomicState?.authTokenCreatedDt ?: getDtNow() + //def formatVal = settings?.useMilitaryTime ? "MMM d, yyyy - HH:mm:ss" : "MMM d, yyyy - h:mm:ss a" + //def tf = new SimpleDateFormat(formatVal) + //if(getTimeZone()) { tf.setTimeZone(getTimeZone()) } + updTimestampMap("authTokenCreatedDt", (getTimestampVal("authTokenCreatedDt") ?: getDtNow())) section() { - paragraph title: "Authorization Info:", "Authorization Date:\n• ${tf?.format(Date.parse("E MMM dd HH:mm:ss z yyyy", atomicState?.authTokenCreatedDt))}", state: "complete" - paragraph "Last Nest Connection:\n• ${tf?.format(Date.parse("E MMM dd HH:mm:ss z yyyy", atomicState.lastDevDataUpd))}" + paragraph title: "Authorization Info:", "Authorization Date:\n• ${getTimestampVal("authTokenCreatedDt")}", state: "complete" + paragraph "Last Nest Connection:\n• ${getTimestampVal("lastDevDataUpd")}" } section("Revoke Authorization Reset:") { href "nestTokenResetPage", title: "Log Out and Reset Nest Token", description: "Tap to Reset Nest Token", required: true, state: null, image: getAppImg("reset_icon.png") @@ -2010,7 +2236,7 @@ def nestTokenResetPage() { return dynamicPage(name: "nestTokenResetPage", install: false) { section ("Resetting Nest Token") { revokeNestToken() - paragraph "Token Reset Complete...", state: "complete" + paragraph "Token Reset Complete...", state: "complete" paragraph "Press Done/Save to return to Login page" } } @@ -2021,72 +2247,138 @@ def nestTokenResetPage() { ******************************************************************************/ def installed() { LogAction("Installed with settings: ${settings}", "debug", true) - if(!parent) { - atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString(), "updatedDt":"Not Set", "freshInstall":true, "shownDonation":false, "shownFeedback":false, "shownChgLog":true, "usingNewAutoFile":true] - sendInstallSlackNotif() - } + atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString(), "updatedDt":"Not Set", "freshInstall":true, "shownDonation":false, "shownFeedback":false, "shownChgLog":true, "usingNewAutoFile":true, "liteAppMode":isAppLiteMode()] + sendInstallSlackNotif() initialize() sendNotificationEvent("${appName()} installed") } def updated() { LogAction("${app.label} Updated...with settings: ${settings}", "debug", true) - if(atomicState?.migrationInProgress == true) { LogAction("Skipping updated() as migration in-progress", "warn", true); return } + atomicState?.pollBlocked = true + atomicState?.pollBlockedReason = "Running updated" + //restStreamHandler(true, false) // stop the rest stream + //atomicState?.restStreamingOn = false + //atomicState.ssdpOn = false + // if(atomicState?.migrationInProgress == true) { LogAction("Skipping updated() as migration in-progress", "warn", true); return } if(atomicState?.needToFinalize == true) { LogAction("Skipping updated() as auth change in-progress", "warn", true); return } initialize() sendNotificationEvent("${appName()} has updated settings") - if(parent) { - atomicState?.lastUpdatedDt = getDtNow() - } + atomicState?.lastUpdatedDt = getDtNow() } def uninstalled() { //LogTrace("uninstalled") - if(parent) { - uninstAutomationApp() - } else { - uninstManagerApp() - } - //sendNotificationEvent("${appName()} is uninstalled") + uninstManagerApp() } def initialize() { - //LogTrace("initialize") - + LogTrace("initialize") + atomicState?.pollBlocked = true + atomicState?.pollBlockedReason = "Running Initialize" + restStreamHandler(true, false) // stop the rest stream + //atomicState?.restStreamingOn = false + atomicState.ssdpOn = false + if(!atomicState?.tsMigration) { timestampMigration() } if(atomicState?.resetAllData || settings?.resetAllData) { - if(fixState()) { return } // runIn of fixState will call initAutoApp() or initManagerApp() - if (!parent) { settingUpdate("resetAllData", "false", "bool") } - } - if(parent) { - runIn(6, "initAutoApp", [overwrite: true]) + if(fixState()) { return } // runIn of fixState will call initManagerApp() + //settingUpdate("resetAllData", "false", "bool") } - else { - if(checkMigrationRequired()) { return true } // This will call updated later - reInitBuiltins() // These are to have these apps release subscriptions to devices (in case of delete) - runIn(21, "initManagerApp", [overwrite: true]) // need to give time for watchdog updates before we try to delete devices. - //runIn(34, "reInitBuiltins", [overwrite: true]) // need to have watchdog/nestmode check if we created devices + if(!isAppLiteMode()) { + runIn(5, "reInitBuiltins", [overwrite: true]) // These are to have these apps release subscriptions to devices (in case of delete) } + runIn(21, "initManagerApp", [overwrite: true]) // need to give time for watchdog updates before we try to delete devices. } def reInitBuiltins() { - initWatchdogApp() - initNestModeApp() - diagLogProcChange((settings?.enDiagWebPage && settings?.enRemDiagLogging)) + checkStorageApp() + if(!isAppLiteMode()) { + initWatchdogApp() + initNestModeApp() // this just removes extras + initStorageApp() + } + if(atomicState?.tsMigration) { initRemDiagApp() } } -def initNestModeApp() { - LogTrace("initNestModeApp") - if(automationNestModeEnabled()) { - def nestModeApp = getChildApps()?.findAll { it?.getAutomationType() == "nMode" } - if(nestModeApp?.size() >= 1) { +def initBuiltin(btype) { + LogTrace("initBuiltin(${btype})") + def keepApp = false + def autoStr = "" + switch (btype) { + case "initNestModeApp": + if(automationNestModeEnabled()) { + keepApp = true + autoStr = "nMode" + } + break + case "initWatchdogApp": + def t0 = settings?.thermostats?.size() + def t1 = atomicState?.thermostats?.size() + if(atomicState?.isInstalled && t0 && t1) { // only need watchDog if we have thermostats + keepApp = true + } + autoStr = "watchDog" + break + case "initRemDiagApp": + if(settings?.enRemDiagLogging) { + keepApp = true + } else { + settingUpdate("enRemDiagLogging", "false","bool") + atomicState?.enRemDiagLogging = false + updTimestampMap("remDiagLogActivatedDt", null) + } + autoStr = "remDiag" + break + case "initStorageApp": + autoStr = "storage" + keepApp = true + def stateSz = getStateSizePerc() + if(stateSz < 58) { keepApp = false } + else { + def kdata = getState()?.findAll { (it?.key in [ "curWeather", "curForecast", "curAstronomy", "curAlerts" ]) } + kdata.each { kitem -> + state.remove(kitem?.key.toString()) + } + } + break + default: + LogAction("initBuiltin BAD btype ${btype}", "warn", true) + break + } + if(isAppLiteMode()) { keepApp = false } + if(autoStr) { + def mynestApp = getChildApps()?.findAll { it?.getAutomationType() == autoStr } + if(keepApp && mynestApp?.size() < 1 && btype != "initNestModeApp") { + LogAction("Installing ${autoStr}", "info", true) + updTimestampMap("lastAnalyticUpdDt", null) + try { + if(btype == "initRemDiagApp") { + addChildApp(appNamespace(), autoAppName(), getRemDiagAppChildLabel(), [settings:[remDiagFlag:["type":"bool", "value":true]]]) + } + if(btype == "initWatchdogApp") { + addChildApp(appNamespace(), autoAppName(), getWatDogAppChildLabel(), [settings:[watchDogFlag:["type":"bool", "value":true]]]) + } + if(btype == "initStorageApp") { + def storageApp = getStorageApp(false) + if(!storageApp) { + addChildApp(appNamespace(), autoAppName(), getStorageAppChildLabel(), [settings:[storageFlag:[type:"bool", value:true]]]) + } + storageAppInst(true) + } + } catch (ex) { + appUpdateNotify(true, "automation") + } + } else if(mynestApp?.size() >= 1) { def cnt = 1 - nestModeApp?.each { chld -> - if(cnt == 1) { - //LogAction("Running Update Command on Nest Mode", "warn", true) + mynestApp?.each { chld -> + if(keepApp && cnt == 1) { + LogTrace("initBuiltin: Running Update Command on ${autoStr}") chld.update() - } else if(cnt > 1) { - LogAction("Deleting Extra nMode (${chld?.id})", "warn", true) + } else if(!keepApp || cnt > 1) { + def slbl = keepApp ? "warn" : "info" + LogAction("initBuiltin: Deleting ${keepApp ? "Extra " : ""}${autoStr} (${chld?.id})", slbl, true) deleteChildApp(chld) + updTimestampMap("lastAnalyticUpdDt", null) } cnt = cnt+1 } @@ -2094,71 +2386,35 @@ def initNestModeApp() { } } +def initNestModeApp() { + initBuiltin("initNestModeApp") +} + def initWatchdogApp() { - LogTrace("initWatchdogApp") - def watDogApp = getChildApps()?.findAll { it?.getAutomationType() == "watchDog" } - if(watDogApp?.size() < 1) { - LogAction("Installing Watchdog App", "info", true) - try { - addChildApp(appNamespace(), autoAppName(), getWatDogAppChildName(), [settings:[watchDogFlag:["type":"bool", "value":true]]]) - } catch (ex) { - appUpdateNotify(true) - } - } else if(watDogApp?.size() >= 1) { - def cnt = 1 - watDogApp?.each { chld -> - if(cnt == 1) { - LogTrace("initWatchdogApp: Running Update Command on Watchdog") - chld.update() - } else if(cnt > 1) { - LogAction("initWatchdogApp: Deleting Extra Watchdog (${chld?.id})", "warn", true) - deleteChildApp(chld) - } - cnt = cnt+1 - } - } + initBuiltin("initWatchdogApp") } def initRemDiagApp() { - LogTrace("initRemDiagApp") - def keepApp = atomicState?.enRemDiagLogging == true ? true : false - def remDiagApp = getChildApps()?.findAll { it?.getAutomationType() == "remDiag" } - if(keepApp && remDiagApp?.size() < 1) { - LogAction("Installing Remote Diag App", "info", true) - try { - addChildApp(appNamespace(), autoAppName(), getRemDiagAppChildName(), [settings:[remDiagFlag:["type":"bool", "value":true]]]) - } catch (ex) { - appUpdateNotify(true) - } - } else if(remDiagApp?.size() >= 1) { - def cnt = 1 - remDiagApp?.each { chld -> - if(keepApp && cnt == 1) { - LogTrace("initRemDiagApp: Running Update Command on Remote Diag") - chld.update() - } else if(!keepApp || cnt > 1) { - def slbl = keepApp ? "warn" : "info" - LogAction("initRemDiagApp: Deleting ${keepApp ? "Extra " : ""}Remote Diag Child (${chld?.id})", slbl, true) - deleteChildApp(chld) - } - cnt = cnt+1 - } - } + initBuiltin("initRemDiagApp") +} + +def initStorageApp() { + initBuiltin("initStorageApp") } def initManagerApp() { - LogTrace("initManagerApp") + LogTrace("initManagerApp (${atomicState?.pollBlocked}) (${atomicState?.pollBlockedReason})") setStateVar() - restStreamHandler(true) // stop the rest stream - atomicState?.restStreamingOn = false - atomicState.ssdpOn = false + //restStreamHandler(true, false) // stop the rest stream unschedule() unsubscribe() + atomicState?.pollingOn = false + atomicState?.restStreamingOn = false + atomicState?.streamPolling = false + atomicState.ssdpOn = false stateCleanup() - atomicState.pollingOn = false - atomicState.lastChildUpdDt = null // force child update on next poll - atomicState.lastForcePoll = null + initStorageApp() def sData = atomicState?.swVer ?: [:] sData["mgrVer"] = appVersion() atomicState?.swVer = sData @@ -2170,41 +2426,101 @@ def initManagerApp() { } if(!addRemoveDevices()) { // if we changed any devices or had an error trying, reset queues and polling atomicState.cmdQlist = [] + if(!isAppLiteMode()) { + runIn(15, "reInitBuiltins", [overwrite: true]) // need to have watchdog/nestmode check if we created devices + } } if(settings?.thermostats || settings?.protects || settings?.cameras || settings?.presDevice || settings?.weatherDevice) { atomicState?.isInstalled = true } else { atomicState.isInstalled = false } - if(atomicState?.autoMigrationComplete == true) { // fix for bug that removed this setting - temporary - def iData = atomicState?.installData - iData["usingNewAutoFile"] = true - atomicState?.installData = iData - } subscriber() - setPollingState() startStopStream() runIn(21, "finishInitManagerApp", [overwrite: true]) } def finishInitManagerApp() { - LogTrace("finishInitManagerApp") + LogTrace("finishInitManagerApp (${atomicState?.pollBlocked}) (${atomicState?.pollBlockedReason})") +// polling is still blocked coming into this + //atomicState?.appCodeIdData = [:] + setPollingState() // polling is unblocked + updTimestampMap("lastChildUpdDt", null) // force child update on next poll + updTimestampMap("lastDevDataUpd", null) + updTimestampMap("lastChildForceUpdDt", null) + updTimestampMap("lastForcePoll", null) if(atomicState?.isInstalled && atomicState?.installData?.usingNewAutoFile) { createSavedNest() if(app.label == "Nest Manager") { app.updateLabel("NST Manager") } + def badAutomation = false + def storId = null + if(!isAppLiteMode()) { + getChildApps()?.sort()?.each { chld -> + chld?.update() + } + } else { + badAutomation = true + } - getChildApps()?.sort()?.each { chld -> chld?.update() } - def tstatAutoApp = getChildApps()?.find { + if (!badAutomation) { + def tstatAutoApp = getChildApps()?.find { + def aa = null + try { + aa = it?.getAutomationType() + def bb = it?.getCurrentSchedule() + def ai = it?.getAutomationsInstalled() + } catch (Exception e) { + LogAction("BAD Automation file ${it?.label?.toString()} (${it?.id}), please INSTALL proper automation file", "error", true) + badAutomation = true + appUpdateNotify(true, "automation") + } + if( !badAutomation && !(aa in ["nMode", "watchDog", "remDiag", "schMot", "storage"]) ) { badAutomation = true } + } + } + if(badAutomation) { + LogAction("Deleting BAD Automations in 10 mins", "warn", true) + runIn(600, "removeBadAutomations", [overwrite: true]) + } + if(resetAllData) { // This is to cleanup state for resetAllData - children are given 90 seconds to fixState() + runIn(90, "cleanupResetSettings", [overwrite: true]) + } + } +} + +def cleanupResetSettings() { + settingUpdate("resetAllData", "false", "bool") + runIn(75, "initialize", [overwrite: true]) // cause cleanup to propagate to child apps +} + +def removeBadAutomations() { + def tstatAutoApp = getChildApps()?.find { + def bad = false + def aa = null + try { + aa = it?.getAutomationType() + def bb = it?.getCurrentSchedule() + def ai = it?.getAutomationsInstalled() + } catch (Exception e) { + LogAction("BAD Automation (${it?.id}) found", "warn", true) + bad = true + } + if( !bad && !(aa in ["nMode", "watchDog", "remDiag", "schMot", "storage"]) ) { bad = true } + if(bad || isAppLiteMode()) { try { - def aa = it?.getAutomationType() - def bb = it?.getCurrentSchedule() - def ai = it?.getAutomationsInstalled() + LogAction("Calling uninstall on Automation (${it?.id})", "warn", true) + it?.uninstAutomationApp() } catch (Exception e) { - LogAction("BAD Automation file ${it?.label?.toString()}, please INSTALL proper automation file", "error", true) - appUpdateNotify(true) + ; } + LogAction("Deleting Automation (${it?.id})", "warn", true) + deleteChildApp(it) + updTimestampMap("lastAnalyticUpdDt", null) } } } +def remDiagAppAvail(available) { + atomicState?.remDiagAppAvailable = (available == true) +} + def createSavedNest() { def str = "createSavedNest" LogTrace("${str}") @@ -2213,7 +2529,7 @@ def createSavedNest() { def bad = false if(settings?.structures && atomicState?.structures) { def structs = getNestStructures() - def newStrucName = structs && structs?."${atomicState?.structures}" ? "${structs[atomicState?.structures]}" : null + def newStrucName = structs && structs?."${atomicState?.structures}" ? "${structs[atomicState?.structures]}" : null if(newStrucName) { bbb.a_structures_setting = settings.structures bbb.a_structures_as = atomicState.structures @@ -2223,7 +2539,7 @@ def createSavedNest() { def t0 = [:] t0 = dData?.thermostats?.findAll { it?.key?.toString() in settings?.thermostats } - LogAction("${str} | Thermostats(${t0?.size()}): ${settings?.thermostats}", "info", false) + LogAction("${str} | Thermostats(${t0?.size()}): ${settings?.thermostats}", "info", true) def t1 = [:] t0?.each { devItem -> LogAction("${str}: Found (${devItem?.value?.name})", "info", false) @@ -2272,17 +2588,22 @@ def createSavedNest() { def t0 = atomicState?.savedNestSettings ?: null def t1 = t0 ? new groovy.json.JsonOutput().toJson(t0) : null def t2 = bbb != [:] ? new groovy.json.JsonOutput().toJson(bbb) : null - atomicState.savedNestSettingslastbuild = bbb - if(!bad && t2 && (!t0 || t1 != t2)) { + if(bad) { atomicState.savedNestSettingsprev = atomicState?.savedNestSettings + atomicState.savedNestSettingslastbuild = bbb + state.remove("savedNestSettings") + } + if(!bad && t2 && (!t0 || t1 != t2)) { atomicState.savedNestSettings = bbb + state.remove("savedNestSettingsprev") + state.remove("savedNestSettingslastbuild") return true } } else { LogAction("${str}: No Structure Settings", "warn", true) } } else { LogAction("${str}: NOT Installed!!!", "warn", true) } return false } -//ERSERS + def mySettingUpdate(name, value, type=null) { if(getDevOpt()) { LogAction("Setting $name set to type:($type) $value", "warn", true) @@ -2477,7 +2798,7 @@ def checkRemapping() { //LogAction("as.thermostats: ${atomicState?.thermostats}", "warn", true) atomicState.thermostats = null def t4 = newvThermostats ? newvThermostats?.size() : 0 - def t5 = atomicState?.vThermostats ? atomicState?.vThermostats.size() : 0 + def t5 = atomicState?.vThermostats ? atomicState?.vThermostats.size() : 0 if(t4 || t5) { if(t4 == t5) { astr += ", AS vThermostats ${newvThermostats}" @@ -2651,24 +2972,23 @@ def askAlexaMQHandler(evt) { } def startStopStream() { - def strEn = (atomicState?.appData?.eventStreaming?.enabled == true || getDevOpt() || betaMarker()) ? true : false - if((!strEn || !settings?.restStreaming) && !atomicState?.restStreamingOn) { + if((!settings?.restStreaming) && !atomicState?.restStreamingOn) { return } - if(strEn && settings?.restStreaming && atomicState?.restStreamingOn) { - runIn(5, "restStreamCheck", [overwrite: true]) + if(settings?.restStreaming && atomicState?.restStreamingOn) { + runIn(45, "restStreamCheck", [overwrite: true]) return } - if(strEn && settings?.restStreaming && !atomicState?.restStreamingOn) { - //LogAction("Sending restStreamHandler(Start) Event to local node service", "debug", true) + if(settings?.restStreaming && !atomicState?.restStreamingOn) { + LogTrace("startStopStream: Stream not on, Sending restStreamHandler(Start) Event to local node service") restStreamHandler() - runIn(5, "restStreamCheck", [overwrite: true]) + runIn(45, "restStreamCheck", [overwrite: true]) } - else if ((!settings?.restStreaming || !strEn) && atomicState?.restStreamingOn) { - //LogAction("Sending restStreamHandler(Stop) Event to local node service", "debug", true) + else if (!settings?.restStreaming && atomicState?.restStreamingOn) { + LogTrace("startStopStream: Streaming should not be running Sending restStreamHandler(Stop) Event to local node service") restStreamHandler(true) - atomicState?.restStreamingOn = false - runIn(5, "restStreamCheck", [overwrite: true]) + //atomicState?.restStreamingOn = false + runIn(45, "restStreamCheck", [overwrite: true]) } } @@ -2681,7 +3001,7 @@ def getRestHost() { def autoHost = settings?.selectedRestDevice ?: null def ip = settings?.restStreamIp ?: null def port = settings?.restStreamPort ?: 3000 - LogTrace("getRestHost: autoHost: ${autoHost} ip: ${ip} port: ${port}") + LogTrace("getRestHost: autoHost: ${autoHost} ip: ${ip} port: ${port}") if(autoHost) { res = autoHost } else { @@ -2695,16 +3015,16 @@ def getRestHost() { return res } -def restStreamHandler(close = false) { - LogTrace("restStreamHandler: close: ${close}") +def restStreamHandler(close = false, resetPoll=true) { + LogTrace("restStreamHandler: close: ${close}, resetPoll: ${resetPoll}") def toClose = close def host = getRestHost() if(!host) { atomicState.restStreamingOn = false; host = atomicState?.lastRestHost ?: null atomicState.lastRestHost = null - if(!host) { return } - toClose = true + return + //toClose = true } else { atomicState.lastRestHost = host } @@ -2716,12 +3036,16 @@ def restStreamHandler(close = false) { LogTrace("restStreamHandler(close: ${close}) host: ${host} lastRestHost: ${atomicState?.lastRestHost}") def connStatus = toClose ? false : true LogAction("restStreamHandler(${connStatus ? "Start" : "Stop"}) Event to local node service", "debug", true) + String hubIp = settings?.restStreamLocalHub?.getLocalIP() + Boolean localStream = (settings?.restStreamLocal == true && hubIp) try { def hubAction = new physicalgraph.device.HubAction( method: "POST", headers: [ "HOST": host, "nesttoken": "${atomicState?.authToken}", + "stHubIp": "${hubIp}", + "localStream": "${localStream}", "connStatus": "${connStatus}", "callback": "${getApiURL()}", "sttoken": "${atomicState?.accessToken}", @@ -2731,11 +3055,16 @@ def restStreamHandler(close = false) { body: "" ) sendHubCommand(hubAction) - } - catch (Exception e) { + } catch (Exception e) { log.error "restStreamHandler Exception $e on $hubAction" atomicState.restStreamingOn = false } + if(toClose) { + atomicState?.restStreamingOn = false + if(atomicState?.streamPolling && resetPoll) { + resetPolling() + } + } } def restStreamCheck() { @@ -2747,6 +3076,8 @@ def restStreamCheck() { return } LogTrace("restStreamCheck host: ${host}") + String hubIp = settings?.restStreamLocalHub?.getLocalIP() + Boolean localStream = (settings?.restStreamLocal == true && hubIp) try { atomicState.lastRestHost = host def hubAction = new physicalgraph.device.HubAction( @@ -2754,6 +3085,8 @@ def restStreamCheck() { headers: [ "HOST": host, "callback": "${getApiURL()}", + "stHubIp": "${hubIp}", + "localStream": "${localStream}", "sttoken": "${atomicState?.accessToken}", "structure": "${atomicState?.structures}" ], @@ -2768,8 +3101,8 @@ def restStreamCheck() { } } -def receiveStreamStatus() { - def resp = request?.JSON +def receiveStreamStatus(eventData=null) { + def resp = eventData == null ? request?.JSON : eventData if(resp) { def t0 = resp?.streaming == true ? true : false def t1 = atomicState?.restStreamingOn @@ -2778,13 +3111,13 @@ def receiveStreamStatus() { } atomicState?.restStreamingOn = t0 if(!settings?.restStreaming && t0) { // suppose to be off - //LogAction("Sending restStreamHandler(Stop) Event to local node service", "debug", false) + //LogAction("receiveStreamStatus: Sending restStreamHandler(Stop) Event to local node service", "debug", true) restStreamHandler(true) } else if (settings?.restStreaming && !atomicState?.restStreamingOn) { // suppose to be on - runIn(21, "startStopStream", [overwrite: true]) + runIn(45, "startStopStream", [overwrite: true]) } if(settings?.restStreaming && t0) { // All good - atomicState?.lastHeardFromNestDt = getDtNow() + updTimestampMap("lastHeardFromNestDt", getDtNow()) if(atomicState?.ssdpOn == true) { unsubscribe() atomicState.ssdpOn = false @@ -2801,15 +3134,18 @@ def receiveStreamStatus() { } } atomicState?.restServiceData = resp - - render contentType: 'text/html', data: "status received...ok", status: 200 + if(eventData) { + return [data: "status received...ok", status: 200] + } else { + render contentType: 'text/html', data: "status received...ok", status: 200 + } } } def uninstManagerApp() { LogTrace("uninstManagerApp") try { - restStreamHandler(true) // stop the rest stream + restStreamHandler(true, false) // stop the rest stream //Revokes Smartthings endpoint token revokeAccessToken() //Revokes Nest Auth Token @@ -2821,7 +3157,7 @@ def uninstManagerApp() { } //If any client related data exists on firebase it will be removed //clearRemDiagData(true) - clearAllAutomationBackupData() + // clearAllAutomationBackupData() //sends notification of uninstall sendNotificationEvent("${appName()} is uninstalled") } @@ -2840,19 +3176,21 @@ def isAutoAppInst() { } def getInstAutoTypesDesc() { - def dat = ["nestMode":0,"watchDog":0, "disabled":0, "remDiag":0, "schMot":["tSched":0, "remSen":0, "fanCtrl":0, "fanCirc":0, "conWat":0, "extTmp":0, "leakWat":0, "humCtrl":0 ]] + def dat = ["nestMode":0, "watchDog":0, "disabled":0, "remDiag":0, "storage":0, "schMot":["tSched":0, "remSen":0, "fanCtrl":0, "fanCirc":0, "conWat":0, "extTmp":0, "leakWat":0, "humCtrl":0 ]] def disItems = [] def nItems = [:] def schMotItems = [] //atomicState?.autoSaVer = minVersions()?.automation?.desc def sData = atomicState?.swVer ?: [:] sData["autoSaVer"] = null + sData["storVer"] = null atomicState?.swVer = sData childApps?.each { a -> - def type = a?.getAutomationType() + def type def ver def dis try { + type = a?.getAutomationType() dis = a?.getIsAutomationDisabled() ver = a?.appVersion() } @@ -2862,16 +3200,16 @@ def getInstAutoTypesDesc() { type = "old" } if(ver) { - def updVer = sData.autoSaVer ?: ver + def updVer = sData?.autoSaVer ?: ver if(versionStr2Int(ver) < versionStr2Int(updVer)) { updVer = ver } sData.autoSaVer = updVer atomicState?.swVer = sData } - if(ver==null || (versionStr2Int(ver) < minVersions()?.automation?.val) || (versionStr2Int(ver) > minVersions()?.automation?.val && !getDevOpt() )) { - LogAction("NST AUTOMATIONS UPDATE REQUIRED: Automation ${a?.label} (v${ver}) | REQUIRED: (v${minVersions()?.automation?.desc}) | Please install the current NST Automations software in the IDE", "error", true) - appUpdateNotify(true) + if(ver == null || (versionStr2Int(ver) < minVersions()?.automation?.val) || (versionStr2Int(ver) > minVersions()?.automation?.val && !getDevOpt())) { + LogAction("NST AUTOMATIONS UPDATE REQUIRED: Automation ${a?.label} (v${ver}) | REQUIRED: (v${minVersions()?.automation?.desc}) | Please install the current NST Automations SmartApp Code in the IDE", "error", true) + appUpdateNotify(true, "automation") } if(dis) { @@ -2885,6 +3223,7 @@ def getInstAutoTypesDesc() { dat.nestMode = dat.nestMode - 1 LogAction("Deleting Extra Nest Mode (${a?.id})", "warn", true) deleteChildApp(a) + updTimestampMap("lastAnalyticUpdDt", null) } break case "schMot": @@ -2895,7 +3234,7 @@ def getInstAutoTypesDesc() { } catch (Exception e) { log.error "BAD Automation file ${a?.label?.toString()}, please RE-INSTALL automation file" - appUpdateNotify(true) + appUpdateNotify(true, "automation") } if(ai) { ai?.each { aut -> @@ -2916,6 +3255,7 @@ def getInstAutoTypesDesc() { dat.watchDog = dat.watchDog - 1 LogAction("Deleting Extra Watchdog (${a?.id})", "warn", true) deleteChildApp(a) + updTimestampMap("lastAnalyticUpdDt", null) } break case "remDiag": @@ -2924,11 +3264,27 @@ def getInstAutoTypesDesc() { dat.remDiag = dat.remDiag - 1 LogAction("Deleting Extra Remote Diagnostic (${a?.id})", "warn", true) deleteChildApp(a) + updTimestampMap("lastAnalyticUpdDt", null) } break + case "storage": + dat["storage"] = dat["storage"] ? dat["storage"]+1 : 1 + if(dat.storage > 1) { + dat.storage = dat.storage - 1 + LogAction("Deleting Extra Storage Child (${a?.id})", "warn", true) + deleteChildApp(a) + updTimestampMap("lastAnalyticUpdDt", null) + } else if(a?.name == "NST Storage") { + LogAction("Deleting Old Storage Child (${a?.id})", "warn", true) + deleteChildApp(a) + updTimestampMap("lastAnalyticUpdDt", null) + } + checkStorageApp() + break default: LogAction("Deleting Unknown Automation (${a?.id})", "warn", true) deleteChildApp(a) + updTimestampMap("lastAnalyticUpdDt", null) break } } @@ -2937,6 +3293,7 @@ def getInstAutoTypesDesc() { def str = "" str += (dat?.watchDog > 0 || dat?.nestMode > 0 || dat?.schMot || dat?.disabled > 0) ? "Installed Automations:" : "" + str += (dat?.storage > 0) ? "\n• Storage (Active)" : "" str += (dat?.watchDog > 0) ? "\n• Watchdog (Active)" : "" str += (dat?.remDiag > 0) ? "\n• Diagnostic (Active)" : "" str += (dat?.nestMode > 0) ? ((dat?.nestMode > 1) ? "\n• Nest Home/Away (${dat?.nestMode})" : "\n• Nest Home/Away (Active)") : "" @@ -2954,12 +3311,20 @@ def getInstAutoTypesDesc() { def subscriber() { subscribe(app, onAppTouch) - if(atomicState.appData?.aaPrefs?.enMultiQueue && settings?.allowAskAlexaMQ) { + if(atomicState.appData?.settings?.askAlexa?.enMultiQueue && settings?.allowAskAlexaMQ) { subscribe(location, "askAlexaMQ", askAlexaMQHandler) //Refreshes list of available AA queues } + //Pushover Manager Init/cleanup + if(settings?.pushoverEnabled == true) { + pushover_init() + } else { pushover_cleanup() } + //Rest Stream Subriptions if(settings?.restStreaming && !getRestHost()) { restSrvcSubscribe() } + if(settings?.restStreaming && settings?.restStreamLocal && settings?.restStreamLocalHub) { + subscribe(location, null, lanStreamEvtHandler, [filterEvents:false]) + } } private adj_temp(tempF) { @@ -2967,7 +3332,7 @@ private adj_temp(tempF) { LogAction("adj_temp: error temp ${tempF} is list", "error", true) } if(getTemperatureScale() == "C") { - return (tempF - 32) * (5 / 9) as Double // + return (tempF - 32) * (5 / 9) as Double } else { return tempF } @@ -2980,6 +3345,9 @@ def setPollingState() { unschedule("poll") atomicState.streamPolling = false } else { + if(!atomicState?.authToken) { + atomicState.pollingOn = false + } if(!atomicState?.pollingOn && atomicState?.authToken) { //LogAction("Polling is ACTIVE", "info", true) atomicState.pollingOn = true @@ -2995,15 +3363,17 @@ def setPollingState() { pollStrTime = Math.max(pollStrTime, theMax) def weatherTimer = pollTime if(atomicState?.weatherDevice) { weatherTimer = (settings?.pollWeatherValue ? settings?.pollWeatherValue.toInteger() : 900) } - def timgcd = gcd([pollTime, pollStrTime, weatherTimer]) + Integer timgcd = gcd([pollTime, pollStrTime, weatherTimer]) def random = new Random() def random_int = random.nextInt(60) - timgcd = (timgcd.toInteger() / 60) < 1 ? 1 : timgcd.toInteger() / 60 + timgcd = (timgcd.div(60) < 1) ? 1 : (timgcd.div(60)) def random_dint = random.nextInt(timgcd.toInteger()) LogAction("POLL scheduled (${random_int} ${random_dint}/${timgcd} * * * ?)", "info", true) schedule("${random_int} ${random_dint}/${timgcd} * * * ?", poll) // this runs every timgcd minutes + atomicState?.pollBlocked = false + atomicState?.pollBlockedReason = null def timChk = atomicState?.streamPolling ? 1200 : 240 - if(!atomicState?.lastDevDataUpd || getLastDevicePollSec() > timChk) { + if(!getTimestampVal("lastDevDataUpd") || getLastDevPollSec() > timChk) { if(atomicState.streamPolling) { poll() } else { poll(true) } @@ -3030,9 +3400,15 @@ private gcd(input = []) { } def onAppTouch(event) { + /* + // ERS Debug to remove + def sData = atomicState?.swVer ?: [:] + sData["mgrVer"] = "tester" + atomicState?.swVer = sData + return + */ stateCleanup() createSavedNest() - fixStuckMigration() poll(true) } @@ -3048,73 +3424,13 @@ def refresh(child = null) { def pollFollow() { poll() } -def fixStuckMigration() { - if(atomicState?.migrationInProgress == true) { - atomicState?.migrationInProgress = false - atomicState?.pollBlocked = false - atomicState?.pollBlockedReason = null - atomicState?.autoMigrationComplete = true - def t0 = atomicState?.installData - t0["usingNewAutoFile"] = true - atomicState?.installData = t0 - } -} - -def cleanRestAutomationTest() { - /* - NOTE: - This is only here to allow testing. - It will be removed after testing is complete - */ - //log.trace "cleanRestAutomationTest..." - def cApps = getChildApps() - atomicState?.pollBlocked = true - atomicState.pollBlockedReason = "Cleaning Automation Migration" - atomicState?.migrationInProgress = true - atomicState?.autoMigrationComplete = true - def foundAll = true - if(keepBackups() == false) { - cApps.each { ca -> - def restId = ca?.getSettingVal("restoreId") - if(restId == null) { - foundAll = false - } - } - if(foundAll) { - cApps.each { ca -> - def restId = ca?.getSettingVal("restoreId") - if(restId != null) { - ca?.settingUpdate("restoreId", null) - } - } - } - } - cApps.each { ca -> - def restId = ca?.getSettingVal("restoreId") - if(restId != null) { - LogAction("CleanRestAutomationTest: removing ${ca?.label} ${restId}", "warn", true) - deleteChildApp(ca) - } - else { - LogAction("CleanRestAutomationTest: enabling ${ca?.label} ${restId}", "warn", true) - ca?.settingUpdate("disableAutomationreq", "false", "bool") - ca?.stateUpdate("disableAutomation", false) - ca?.stateUpdate("disableAutomationDt", null) - ca?.update() - } - } - atomicState?.migrationInProgress = false - atomicState?.pollBlocked = false - atomicState?.pollBlockedReason = null - atomicState?.autoMigrationComplete = false - def t0 = atomicState?.installData - t0["usingNewAutoFile"] = false - atomicState?.installData = t0 -} - def checkIfSwupdated() { - if(checkMigrationRequired()) { return true } + // if(checkMigrationRequired()) { return true } if(atomicState?.swVer?.mgrVer != appVersion()) { + def sData = atomicState?.swVer ?: [:] + sData["mgrVer"] = appVersion() + atomicState?.swVer = sData + updTimestampMap("lastAnalyticUpdDt", null) LogAction("checkIfSwupdated: new version ${appVersion()}", "info", true) def iData = atomicState?.installData iData["updatedDt"] = getDtNow().toString() @@ -3122,347 +3438,19 @@ def checkIfSwupdated() { iData["shownFeedback"] = false iData["shownDonation"] = false atomicState?.installData = iData -/* Updated does this - def sData = atomicState?.swVer ?: [:] - sData["mgrVer"] = appVersion() - atomicState?.swVer = sData - def cApps = getChildApps() - if(cApps) { - cApps?.sort()?.each { chld -> - chld?.update() - } - } -*/ +// force full fixState + settingUpdate("resetAllData", "true", "bool") + atomicState.resetAllData = false + atomicState.pollBlocked = true + atomicState.pollBlockedReason = "Software Update pending" + runIn(20, "updated", [overwrite: true]) + //updated() sendInstallSlackNotif(false) - updated() - return true - } - return false -} - -/* NOTE: - MIGRATION Pre-Check - This will be called as part of the version change logic. - It looks to see if the file version is greater than a set number and that the atomicState.autoMigrationComplete is false or null, - If the to are ok it schedules the "doAutoMigrationProcess" method for 5 seconds. -*/ -def checkMigrationRequired() { - if(atomicState?.migrationInProgress == true) { return true } - else if(atomicState?.installData?.usingNewAutoFile == true) { return false } - if(allowMigration()) { - if((versionStr2Int(appVersion()) >= 454 && !atomicState?.autoMigrationComplete == true)) { - LogAction("checkMigrationRequired: Scheduled Migration Process to New Automation File...(5 seconds)", "info", true) - //atomicState?.migrationInProgress == true - runIn(5, "doAutoMigrationProcess", [overwrite: true]) - return true - } - } - return false -} - -/* NOTE: - This is method creates the settings map with these items [type, value] so it can be easily restored. - The input reference data used is stored on our firebase -*/ -def buildSettingsMap() { - def inputData = getWebData([uri: "https://st-nest-manager.firebaseio.com/restoreInputData.json", contentType:"application/json"], "inputType", false) - def settingsMap = [:] - def setData = getSettings()?.sort()?.findAll { it } - setData?.sort().each { item -> - def itemType = inputData?.inputs?.find { item?.key.toString().contains(it?.key.toString()) } - settingsMap[item?.key] = ["type":itemType?.value, "value":item?.value] - } - return settingsMap -} - -/* NOTE: - This is method creates the JSON that is sent to Firebase with the Settings and State data -*/ -def createAutoBackupJson() { - //log.trace "createAutoBackupJson..." - def noShow = ["curAlerts", "curAstronomy", "curForecast", "curWeather", "detailEventHistory", "detailExecutionHistory", "evalExecutionHistory", "activeSchedData", "resetAllData"] - for(def i=1; i <= 8; i++) { noShow.push("schMot_${i}_MotionActiveDt"); noShow.push("schMot_${i}_MotionInActiveDt"); noShow.push("schMot_${i}_oldMotionActive"); } - def stData = getState()?.sort()?.findAll { !(it.key in noShow) } - def stateData = [:] - stData?.sort().each { item -> - stateData[item?.key] = item?.value - } - def setData = buildSettingsMap() - setData?.sort().each { item -> - //log.debug "item: $item" - def itemVal = item?.value?.value - def itemType = item?.value?.type - def tmpList = [] - def getIds4These = ["phone", "contact"] - def setObj = null - if(itemType?.contains("capability") || itemType in getIds4These) { - if(itemVal instanceof List) { setObj = settings[item?.key]?.collect { it?.id } } - else { setObj = settings[item?.key]?.id } - } - else { - if(itemType == "mode" || itemVal instanceof Integer || itemVal instanceof Double || itemVal instanceof Boolean || itemVal instanceof Float || itemVal instanceof Long || itemVal instanceof BigDecimal) { - setObj = itemVal - } - else { setObj = itemVal.toString() } - } - //log.debug "setting item ${item?.key}: ${getObjType(itemVal)} | result: $setObj" - setData[item?.key]?.value = setObj - } - setData["automationTypeFlag"] = getAutoType().toString() - //setData["backedUpData"] = true - def data = [:] - data["appLabel"] = app.label - data["stateData"] = stateData - data["settingsData"] = setData - data["backupDt"] = getDtNow() - def resultJson = new groovy.json.JsonOutput().toJson(data) - //log.debug "resultJson: $resultJson" - return resultJson -} - -// Child Method -// This is only necessary in the manager code to allow the backup to be created for migration to the new automation file -def backupConfigToFirebase() { - //log.trace "backupConfigToFirebase..." - unschedule() - unsubscribe() - uninstAutomationApp() // Cleanup any parent state this child owns - def data = createAutoBackupJson() - return parent?.sendAutomationBackupData(data, app.id) -} - -//Manager only -def sendAutomationBackupData(data, appId) { - try { - sendFirebaseData(data, "backupData/clients/${atomicState?.installationId}/automationApps/${appId}.json", null, "Automation ($appId) Backup", true) - } catch (ex) { - LogAction("sendAutomationBackupData Exception: ${ex}", "error", true) - return false - } -} - -def removeAutomationBackupData(childId, lbl=null) { - LogAction("removeAutomationBackupData(${lbl ? "$lbl" : "$childId"})", "info", true) - return removeFirebaseData("backupData/clients/${atomicState?.installationId}/automationApps/${childId}.json") -} - -def clearAllAutomationBackupData() { - LogAction("cleanAllAutomationBackupData()...", "trace", true) - return removeFirebaseData("backupData/clients/${atomicState?.installationId}.json") -} - -def getAutomationBackupData() { - return getWebData([uri: "https://st-nest-manager.firebaseio.com/backupData/clients/${atomicState?.installationId}/automationApps.json", contentType:"application/json"], "getAutomationBackup", false) -} - -def migrationInProgress() { - return atomicState?.migrationInProgress == true ? true : false -} - -/* - NOTE: MIGRATION STEP 1 - This is the process that is called to kick off the backup/restore process. - It set the state values of pollBlocked and migrationInProgress to true to prevent any polling - PARENT METHOD -*/ -void doAutoMigrationProcess() { - LogAction("doAutoMigrationProcess...", "trace", true) - if(atomicState?.migrationInProgress == true) { LogAction("Migration already in progress", "error", true) } - atomicState?.pollBlocked = true - atomicState?.pollBlockedReason = "Automation Migration in Progress" - atomicState?.migrationInProgress = true - atomicState?.migrationState1 = "Step 1 Start" - - // This is to control the parent/child state to reset using fixState() - atomicState?.resetAllData = false - settingUpdate("resetAllData", "false") - - def cApps = getChildApps() - if(cApps) { - cApps?.each { ca -> - def t0 = ca?.settings?.restoredFromBackup - atomicState?.migrationState1 = "Step 1 Backup - ${ca.label}" - if(t0 == null && backupAutomation(ca)) { - LogAction("backed up ${ca?.label}", "debug", true) - } else { - if(t0) { LogAction("skipping backup of the new style automation ${ca.label}", "debug", true) } - else { LogAction("backup failed of automation ${ca.label}", "warn", true) } - } - } - atomicState?.migrationState1 = "Step 1 Finish - Restore Scheduled" - runIn(15, "processAutoRestore", [overwrite:true]) - LogAction("Scheduled restore process for (15 seconds)...", "info", true) - } else { - atomicState?.migrationState1 = "Step 1 Finish - Nothing to Restore" - LogAction("There are no automations to restore.", "warn", true) - finishMigrationProcess(false) - } -} - -/* - NOTE: MIGRATION STEP 2 - This is the process calls the backupConfigToFirebase method on every child - PARENT METHOD -*/ -def backupAutomation(child) { - if(child?.backupConfigToFirebase()) { - child?.stateUpdate("lastBackupDt", getDtNow()) return true } return false } -/* - NOTE: MIGRATION STEP 3 - This process calls the automationRestore method with all of the backup data to restore - PARENT METHOD -*/ -void processAutoRestore() { - LogAction("processAutoRestore...", "trace", true) - atomicState?.migrationState3 = "Step 3 Start" - def backupData = getAutomationBackupData() - if(backupData instanceof List || backupData instanceof Map) { - atomicState?.migrationState3 = "Step 3 Automation Restore" - automationRestore(backupData) - } - atomicState?.migrationState3 = "Step 3 Finish" -} - -/* - NOTE: MIGRATION STEP 4 - This is the actual automation restore method for installing the automations from the backups - It loops through each backed up automation id and creates the map to send and creates the new automation - using the new file. - PARENT METHOD -*/ -def automationRestore(data, id=null) { - LogAction("automationRestore... size: ${data?.size()}", "trace", true) - try { - if(data) { - data?.each { bApp -> - if(id && id.toString() != bApp?.key.toString()) { return } - def appLbl = bApp?.value?.appLabel.toString() - def setData = bApp?.value?.settingsData - setData["restoreId"] = ["type":"text", "value":bApp?.key] - setData["restoredFromBackup"] = ["type":"bool", "value":true] - setData["restoreCompleted"] = ["type":"bool", "value":false] - setData["automationTypeFlag"] = ["type":"text", "value":setData?.automationTypeFlag] - - atomicState?.migrationState4 = "Step 4 Automation Restore - Restoring [${setData?.automationTypeFlag?.value}] Automation Named: ($appLbl)...." - LogAction("Restoring [${setData?.automationTypeFlag?.value}] Automation Named: ($appLbl)....", "info", true) - // log.debug "setData: $setData" - try { - addChildApp(appNamespace(), autoAppName(), "${appLbl} (NST)", [settings:setData]) - } catch (ex) { - appUpdateNotify(true) - return false - } - postChildRestore(bApp?.key) - } - atomicState?.migrationState4 = "Step 4 Automation Restore - Finishing" - runIn(25, "finishMigrationProcess", [overwrite:true]) - LogAction("Scheduling finishMigrationProcess for (25 seconds)...", "debug", true) - return true - } - } catch (ex) { - log.error "automationRestore Exception:", ex - } - return false -} - -/* - NOTE: MIGRATION STEP 5 - This is called by the child automations initAutoApp() method after the addChildApp() - creates that app from backup. On the first initialazation of the child it calls the - parent to restore the stateData from backup. BACKUP MUST STILL EXIST - PARENT METHOD -*/ -def callRestoreState(child, restId) { - atomicState?.migrationState5 = "Step 5 callRestoreState - Start ${child.label} RestoreID: ${restId}" - LogAction("callRestoreState ${child.label} RestoreID: ${restId}", "trace", true) - //log.debug "child: [Name: ${child.label} || ID: ${child?.getId()} | RestoreID: $restId" - if(restId) { - def data = getAutomationBackupData() - //log.debug "callRestoreState data: $data" - def newData = data.find { it?.key?.toString() == restId?.toString() } - if(newData?.value?.stateData) { - atomicState?.migrationState5 = "Step 5 callRestoreState - restoring child ${child.label} state RestoreID: ${restId}" - newData?.value?.stateData?.each { sKey -> - child?.stateUpdate(sKey?.key, sKey?.value) - } - return true - } else { - atomicState?.migrationState5 = "Step 5 callRestoreState - no backup data child ${child.label} RestoreID: ${restId}" - LogAction("Backup Data not found: ${child.label} RestoreID: ${restId}", "error", true) - } - } - return false -} - -/* - NOTE: MIGRATION STEP 3 (Really part of STEP 3) - This is called by the child once it's state data has been restored and it's purpose is - finalize the restore setting values and disable or remove the old automations. - The removal is controlled by the method keepBackups(). - PARENT METHOD -*/ -def postChildRestore(childId) { - atomicState?.migrationState3A = "Step 3A Start postChildRestore(childId: $childId)" - LogAction("postChildRestore(childId: $childId)", "trace", true) - def cApp = getChildApps() - cApp?.each { ca -> - atomicState?.migrationState3A = "Step 3A postChildRestore Checking Automation (${ca?.label})..." - LogAction("postChildRestore Checking Automation (${ca?.label})...", "info", true) - if(ca?.id.toString() == childId) { - if(keepBackups() == false) { - atomicState?.migrationState3A = "Step 3A postChildRestore Removing Old Automation (${ca?.label})..." - LogAction("postChildRestore Removing Old Automation (${ca?.label})...", "warn", true) - deleteChildApp(ca) - } else { - ca?.settingUpdate("disableAutomationreq", "true", "bool") - ca?.stateUpdate("disableAutomation", true) - ca?.stateUpdate("disableAutomationDt", getDtNow()) - ca?.update() - } - } else { - atomicState?.migrationState3A = "Step 3A postChildRestore No Match for Automation (${ca?.label})..." - LogAction("postChildRestore No Match for Automation (${ca?.label})...", "info", true) - } - } -} - -/* - NOTE: MIGRATION 6 - This is the final part of the migration process. It's supposed to if Successful restore polling state, - and mark the migration complete. Otherwise it leaves them set so the migration will try again after the - update is called. - PARENT METHOD -*/ -void finishMigrationProcess(result=true) { - atomicState?.migrationState6 = "Step 6 start - finishMigrationProcess result: $result" - LogAction("finishMigrationProcess result: $result", "trace", true) - if(result) { - LogAction("Auto Migration Process is complete...", "info", true) - def t0 = atomicState?.installData - t0["usingNewAutoFile"] = true - atomicState?.installData = t0 - } else { - LogAction("Auto Migration did not do anything...", "warn", true) - } - atomicState?.pollBlocked = false - atomicState?.pollBlockedReason = null - atomicState?.migrationInProgress = false - atomicState?.autoMigrationComplete = true - - // This is to force the parent/child state to reset using fixState() - atomicState?.resetAllData = false - settingUpdate("resetAllData", "true") - - // This will perform a cleanup of any backup data that wasn't removed - if(keepBackups() == false) { clearAllAutomationBackupData() } - app.update() -} - def poll(force = false, type = null) { if(isPollAllowed()) { if(checkIfSwupdated()) { return } @@ -3480,8 +3468,8 @@ def poll(force = false, type = null) { if(getLastHeardFromNestSec() > pollTimeout) { if(settings?.restStreaming && atomicState?.restStreamingOn) { LogAction("Have not heard from Rest Stream", "warn", true) - restStreamHandler(true) // close the stream if we have not heard from it in a while - atomicState?.restStreamingOn = false + restStreamHandler(true, false) // close the stream if we have not heard from it in a while + //atomicState?.restStreamingOn = false } } @@ -3502,17 +3490,6 @@ def poll(force = false, type = null) { } startStopStream() - //def pollStrTime = !settings?.pollStrValue ? 180 : settings?.pollStrValue.toInteger() - //if(pollTime < 60 || pollStrTime < 60) { - if(pollTime < 60 && inReview() && !atomicState?.apiRateLimited) { - if(atomicState?.pollTock) { - atomicState.pollTock = false - runIn(30, "pollFollow", [overwrite: true]) - } else { - atomicState.pollTock = true - } - } - def okStruct = ok2PollStruct() def okDevice = ok2PollDevice() def okMeta = ok2PollMetaData() @@ -3520,56 +3497,57 @@ def poll(force = false, type = null) { def dev = false def str = false if(!okDevice && !okStruct && !(getLastHeardFromNestSec() > pollTimeout*2)) { - LogAction("No Device or Structure poll - Devices Last Updated: ${getLastDevicePollSec()} seconds ago | Structures Last Updated ${getLastStructPollSec()} seconds ago", "info", true) - } - else { + LogAction("No Device or Structure poll - Devices Last Updated: ${getLastDevPollSec()} seconds ago | Structures Last Updated ${getLastStrPollSec()} seconds ago", "info", true) + } else { def sstr = "" - def allowAsync = false - def metstr = "sync" - if(atomicState?.appData && atomicState?.appData?.pollMethod?.allowAsync) { - allowAsync = true - metstr = "async" - } + def metstr = "async" if(okStruct) { - sstr += "Updating Structure Data (Last Updated: ${getLastStructPollSec()} seconds ago)" - if(allowAsync) { - str = queueGetApiData("str") - } else { - str = getApiData("str") - } + sstr += "Updating Structure Data (Last Updated: ${getLastStrPollSec()} seconds ago)" + str = queueGetApiData("str") } if(okDevice) { sstr += sstr != "" ? " | " : "" - sstr += "Updating Device Data (Last Updated: ${getLastDevicePollSec()} seconds ago)" - if(allowAsync) { - dev = queueGetApiData("dev") - } else { - dev = getApiData("dev") - } + sstr += "Updating Device Data (Last Updated: ${getLastDevPollSec()} seconds ago)" + dev = queueGetApiData("dev") } if(okMeta) { sstr += sstr != "" ? " | " : "" sstr += "Updating Meta Data(Last Updated: ${getLastMetaPollSec()} seconds ago)" - if(allowAsync) { - meta = queueGetApiData("meta") - } else { - meta = getApiData("meta") - } + meta = queueGetApiData("meta") } if(sstr != "") { LogAction("${sstr} (${metstr})", "info", true) } - if(allowAsync) { return } + return } finishPoll(str, dev) - } else if(atomicState?.clientBlacklisted) { - LogAction("Client poll is BLACKLISTED. Please contact the Developer", "warn", true) + } else if(atomicState?.cltBlacklisted) { + LogAction("Client poll is BLACKLISTED. Please contact the Developer", "warn", true) finishPoll(false, true) } } def finishPoll(str=null, dev=null) { LogTrace("finishPoll($str, $dev) received") - if(atomicState?.pollBlocked) { LogAction("Polling BLOCKED | Reason: (${atomicState?.pollBlockedReason})", "trace", true); schedNextWorkQ(null); return } - if(dev || str || atomicState?.forceChildUpd || atomicState?.needChildUpd) { updateChildData() } + def lastDevUpd = getLastChildUpdSec() + if(!atomicState?.pollingOn) { + LogAction("finishPoll: Polling not ON", "warn", true); + return + } + if(atomicState?.pollBlocked) { + LogAction("finishPoll: Polling BLOCKED | Reason: (${atomicState?.pollBlockedReason})", "warn", true); + if( (atomicState?.apiRateLimited && lastDevUpd > 35*60) || (lastDevUpd > 45*60 && (atomicState?.needChildUpd || atomicState?.forceChildUpd) ) ) { + LogAction("finishPoll: ReRunning Updated() | Polling blocked | Last device update ${lastDevUpd} | Rate Limited: ${atomicState?.apiRateLimited}", "warn", true); + runIn(5, "updated", [overwrite: false]) // ensure it does not keep delaying + return + } + if(getLastAnyCmdSentSeconds() > 75) { // if poll is blocked and we have not sent a command recently, try to kick the queues + schedNextWorkQ(); + } + return + } + if(getLastChildForceUpdSec() > (15*60)-2) { // if nest goes silent (no changes coming back); force all devices to get an update so they can check health + atomicState.forceChildUpd = true + } + if(dev || str || atomicState?.forceChildUpd || atomicState?.needChildUpd) { runIn(1, "updateChildData", [overwrite : true]) } updateWebStuff() notificationCheck() //Checks if a notification needs to be sent for a specific event broadcastCheck() @@ -3580,6 +3558,7 @@ def finishPoll(str=null, dev=null) { def resetPolling() { atomicState.pollingOn = false + atomicState.streamPolling = false unschedule("poll") unschedule("finishPoll") unschedule("postCmd") @@ -3588,7 +3567,9 @@ def resetPolling() { } def schedFinishPoll(devChg) { - finishPoll(false, devChg) + if(isPollAllowed()) { + finishPoll(false, devChg) + } return } @@ -3599,7 +3580,8 @@ def forcedPoll(type = null) { pollWaitVal = Math.max(pollWaitVal, 10) if(lastFrcdPoll > pollWaitVal) { // This limits manual forces to 10 seconds or more - atomicState?.lastForcePoll = getDtNow() + updTimestampMap("lastForcePoll", getDtNow()) + atomicState?.workQrunInActive = false atomicState?.pollBlocked = false atomicState?.pollBlockedReason = null cmdProcState(false) @@ -3617,17 +3599,18 @@ def forcedPoll(type = null) { LogAction("Updating Meta Data (forcedPoll)", "info", true) getApiData("meta") } - atomicState?.lastWebUpdDt = null - atomicState?.lastWeatherUpdDt = null - atomicState?.lastForecastUpdDt = null - schedNextWorkQ(null) + updTimestampMap("lastWebUpdDt", null) + updTimestampMap("lastWeatherUpdDt" , null) + updTimestampMap("lastForecastUpdDt", null) + schedNextWorkQ() } else { LogAction("Too Soon for Update; Elapsed (${lastFrcdPoll}) seconds; minimum (${settings?.pollWaitVal})", "debug", true) atomicState.needStrPoll = true atomicState.needDevPoll = true } atomicState.forceChildUpd = true - updateChildData() + //runIn(1, "updateChildData", [overwrite : true]) + //updateChildData() } def postCmd() { @@ -3636,8 +3619,8 @@ def postCmd() { } def getApiData(type = null) { - //LogTrace("getApiData($type)") - LogAction("getApiData($type)", "info", false) + LogTrace("getApiData($type)") + //LogAction("getApiData($type)", "info", false) def result = false if(!type || !atomicState?.authToken) { return result } @@ -3658,10 +3641,10 @@ def getApiData(type = null) { try { httpGet(params) { resp -> if(resp?.status == 200) { - atomicState?.lastHeardFromNestDt = getDtNow() + updTimestampMap("lastHeardFromNestDt", getDtNow()) apiIssueEvent(false) - atomicState?.apiRateLimited = false - atomicState?.apiCmdFailData = null + //atomicState?.apiRateLimited = false + //atomicState?.apiCmdFailData = null if(type == "str") { def t0 = resp?.data //LogTrace("API Structure Resp.Data: ${t0}") @@ -3673,21 +3656,21 @@ def getApiData(type = null) { atomicState.structName = newStrucName ?: atomicState?.structName locationPresNotify(getLocationPresence()) } - incApiStrReqCnt() + incrementCntByKey("apiStrReqCnt") } else if(type == "dev") { def t0 = resp?.data //LogTrace("API Device Resp.Data: ${t0}") def chg = didChange(atomicState?.deviceData, t0, "dev", "poll") if(chg) { result = true } - incApiDevReqCnt() + incrementCntByKey("apiDevReqCnt") } else if(type == "meta") { //LogTrace("API Metadata Resp.Data: ${resp?.data}") def nresp = resp?.data?.metadata def chg = didChange(atomicState?.metaData, nresp, "meta", "poll") if(chg) { result = true } - incApiMetaReqCnt() + incrementCntByKey("apiMetaReqCnt") } } else { LogAction("getApiData - ${type} Received: Resp (${resp?.status})", "error", true) @@ -3697,8 +3680,7 @@ def getApiData(type = null) { } } } catch (ex) { - apiIssueEvent(true) - atomicState?.apiRateLimited = false + //atomicState?.apiRateLimited = false atomicState.forceChildUpd = true log.error "getApiData (type: $type) Exception:", ex if(ex instanceof groovyx.net.http.HttpResponseException && ex?.response) { @@ -3709,6 +3691,7 @@ def getApiData(type = null) { else if(type == "meta") { atomicState?.needMetaPoll = true } sendExceptionData(ex, "getApiData") } + apiIssueEvent(true) } return result } @@ -3749,13 +3732,12 @@ def queueGetApiData(type = null, newUrl = null) { def procNestResponse(resp, data) { LogTrace("procNestResponse(${data?.type})") - LogAction("procNestResponse | resp: $resp | data: $data", "info", false) + LogAction("procNestResponse | Status: ${resp?.getStatus()} | data: $data", "info", false) def str = false def dev = false def meta = false def type = data?.type try { - if(!type) { return } if(resp?.status == 307) { @@ -3767,14 +3749,14 @@ def procNestResponse(resp, data) { } if(resp?.status == 200) { - atomicState?.lastHeardFromNestDt = getDtNow() + updTimestampMap("lastHeardFromNestDt", getDtNow()) apiIssueEvent(false) - atomicState?.apiRateLimited = false - atomicState?.apiCmdFailData = null + //atomicState?.apiRateLimited = false + //atomicState?.apiCmdFailData = null if(type == "str") { def t0 = resp?.json //LogTrace("API Structure Resp.Data: ${t0}") - if(atomicState?.structData == null) { atomicState?.structData = t0 } + //if(atomicState?.structData == null) { atomicState?.structData = t0 } def chg = didChange(atomicState?.structData, t0, "str", "poll(async)") if(chg) { str = true @@ -3783,7 +3765,7 @@ def procNestResponse(resp, data) { locationPresNotify(getLocationPresence()) } atomicState.qstrRequested = false - incApiStrReqCnt() + incrementCntByKey("apiStrReqCnt") } if(type == "dev") { def t0 = resp?.json @@ -3793,7 +3775,7 @@ def procNestResponse(resp, data) { dev = true } atomicState.qdevRequested = false - incApiDevReqCnt() + incrementCntByKey("apiDevReqCnt") } if(type == "meta") { def nresp = resp?.json?.metadata @@ -3802,7 +3784,7 @@ def procNestResponse(resp, data) { if(chg) { meta = true } - incApiMetaReqCnt() + incrementCntByKey("apiMetaReqCnt") } } else { def tstr = (type == "str") ? "Structure" : ((type == "dev") ? "Device" : "Metadata") @@ -3820,11 +3802,12 @@ def procNestResponse(resp, data) { atomicState.qdevRequested = false } if((atomicState?.qdevRequested == false && atomicState?.qstrRequested == false) && (dev || atomicState?.forceChildUpd || atomicState?.needChildUpd)) { - finishPoll(true, true) + if(isPollAllowed()) { + finishPoll(true, true) + } } } catch (ex) { - log.error "procNestResponse (type: $type) Exception:", ex def tstr = (type == "str") ? "Structure" : ((type == "dev") ? "Device" : "Metadata") tstr += " Poll async" //LogAction("procNestResponse - Received $tstr: Resp (${resp?.status})", "error", true) @@ -3846,18 +3829,19 @@ def procNestResponse(resp, data) { if(type == "str") { atomicState.needStrPoll = true } else if(type == "dev") { atomicState?.needDevPoll = true } else if(type == "meta") { atomicState?.needMetaPoll = true } + log.error "procNestResponse (type: $type) | Exception:", ex sendExceptionData("${ex}", "procNestResponse_${type}") } } -def receiveEventData() { +def receiveEventData(eventData=null) { def status = [:] try { - def evtData = request?.JSON + def evtData = eventData == null ? request?.JSON : eventData //LogAction("evtData: $evtData", "trace", true) def devChgd = false def gotSomething = false - if(evtData?.data && settings?.restStreaming) { + if(evtData?.data && settings?.restStreaming && atomicState?.restStreamingOn) { if(evtData?.data?.devices) { //LogTrace("API Device Resp.Data: ${evtData?.data?.devices}") gotSomething = true @@ -3884,72 +3868,144 @@ def receiveEventData() { //LogTrace("API Metadata Resp.Data: ${evtData?.data?.metadata}") gotSomething = true def chg = didChange(atomicState?.metaData, evtData?.data?.metadata, "meta", "stream") - if(!chg) { - LogTrace("got metaData") - } + if(!chg) { LogTrace("got metaData") } } } else { - LogTrace("receiveEventData: Sending restStreamHandler(Stop)") - restStreamHandler(true) + def forceStop = false + if(!settings?.restStreaming) { forceStop = true } + if(!forceStop && !atomicState?.restStreamingOn) { + LogAction("receiveEventData: stream not on yet, ignoring", "debug", true) + } + if(forceStop) { + LogAction("receiveEventData: Sending restStreamHandler(Stop)", "warn", true) + restStreamHandler(true) + } } if(gotSomething) { - atomicState?.lastHeardFromNestDt = getDtNow() + updTimestampMap("lastHeardFromNestDt", getDtNow()) if(atomicState?.ssdpOn == true) { unsubscribe() //These were causing exceptions - atomicState.ssdpOn = false + atomicState?.ssdpOn = false subscriber() } - apiIssueEvent(false) - atomicState?.apiRateLimited = false - atomicState?.apiCmdFailData = null - incRestStrEvtCnt() + //apiIssueEvent(false) + //atomicState?.apiRateLimited = false + //atomicState?.apiCmdFailData = null + incrementCntByKey("apiRestStrEvtCnt") } if(atomicState?.forceChildUpd || atomicState?.needChildUpd || devChgd) { schedFinishPoll(devChgd) } - status = ["data":"status received...ok", "code":200] + status = [data:"status received...ok", code:200] } catch (ex) { log.error "receiveEventData Exception:", ex LogAction("receiveEventData Exception: ${ex}", "error", true) - status = ["data":"${ex?.message}", "code":500] + status = [data:"${ex?.message}", code:500] + //apiIssueEvent(true) + } + if(eventData) { + return status + } else { + render contentType: 'text/html', data: status?.data, status: status?.code + } +} + +def lanStreamEvtHandler(evt) { + // log.trace "lanStreamEvtHandler..." + def status = [:] + try { + def msg = parseLanMessage(evt?.description) + Map headerMap = msg?.headers + // log.debug "lanStreamEvtHandler... | headers: ${headerMap}" + Map msgData = [:] + if (headerMap?.size()) { + if (headerMap?.evtSource && headerMap?.evtSource == "NST_Stream") { + if (msg?.body != null) { + def slurper = new groovy.json.JsonSlurper() + msgData = slurper.parseText(msg?.body) + // log.debug "msgData: $msgData" + if(headerMap?.evtType) { + switch(headerMap?.evtType) { + case "streamStatus": + status = receiveStreamStatus(msgData) + break + case "sendEventData": + status = receiveEventData(msgData) + break + } + } + } + } + } + } catch (ex) { + log.error "lanStreamEvtHandler Exception:", ex + status = [data:"${ex?.message}", code: 500] } render contentType: 'text/html', data: status?.data, status: status?.code } def didChange(old, newer, type, src) { - //LogTrace("didChange: type: $type src: $src") - def result = false - def srcStr = src.toString().toUpperCase() + //LogTrace("didChange: type: $type src: $src") + Boolean result = false + String srcStr = src.toString().toUpperCase() if(newer != null) { if(type == "str") { - atomicState?.lastStrucDataUpd = getDtNow() + updTimestampMap("lastStrDataUpd", getDtNow()) atomicState.needStrPoll = false - if(atomicState?.structures) { - LogAction("NestAPI AWAY Debug | Current: (${newer[atomicState?.structures]?.away})${(newer[atomicState?.structures]?.away != old[atomicState?.structures]?.away) ? " | Previous: (${old[atomicState?.structures]?.away})" : ""}", "trace", false) + newer.each { + if(it?.value) { + def myId = it?.value?.structure_id + if(myId) { + newer[myId].wheres = [:] + } + } } } if(type == "dev") { - atomicState?.lastDevDataUpd = getDtNow() + updTimestampMap("lastDevDataUpd", getDtNow()) atomicState?.needDevPoll = false + newer.each { t -> // This reduces stored state size + def dtyp = t.key + t.value.each { + if(it?.value) { + def myId = it?.value?.device_id + if(myId) { + newer."${dtyp}"[myId].where_id = "" + if(newer."${dtyp}"[myId]?.app_url) { + newer."${dtyp}"[myId].app_url = "" + } + if(newer."${dtyp}"[myId]?.last_event?.app_url) { + newer."${dtyp}"[myId].last_event.app_url = "" + } + if(newer."${dtyp}"[myId]?.last_event?.image_url) { + newer."${dtyp}"[myId].last_event.image_url = "" + } + } + } + } + } } if(type == "meta") { - atomicState?.lastMetaDataUpd = getDtNow() + updTimestampMap("lastMetaDataUpd", getDtNow()) atomicState.needMetaPoll = false } if(old != newer) { if(type == "str") { - def t0 = atomicState?.structData?.size() && atomicState?.structures ? atomicState?.structData[atomicState?.structures] : null - def t1 = newer && atomicState?.structures ? newer[atomicState?.structures] : null + def tt0 = atomicState?.structData?.size() ? atomicState?.structData : null + // Null safe does not work on array references that miss + def t0 = tt0 && atomicState?.structures && tt0?."${atomicState?.structures}" ? tt0[atomicState?.structures] : null + def t1 = newer && atomicState?.structures && newer?."${atomicState?.structures}" ? newer[atomicState?.structures] : null + if(t1 && t0 != t1) { result = true atomicState?.forceChildUpd = true LogTrace("structure old newer not the same ${atomicState?.structures}") // whatChanged(t0, t1, "/structures", "structure") - if(atomicState?.enRemDiagLogging == true && settings?.showDataChgdLogs != true) { - LogAction("API Structure Data HAS Changed ($srcStr)", "info", true) - } else { + if(settings?.showDataChgdLogs == true && atomicState?.enRemDiagLogging != true) { def chgs = getChanges(t0, t1, "/structures", "structure") if(chgs) { LogAction("STRUCTURE Changed ($srcStr): ${chgs}", "info", true) } + } else { + LogAction("API Structure Data HAS Changed ($srcStr)", "info", true) } } atomicState?.structData = newer @@ -4036,7 +4092,7 @@ def didChange(old, newer, type, src) { } } } - //LogAction("didChange: type: $type src: $src result: $result", "info", true) + //LogAction("didChange: type: $type src: $src result: $result", "info", true) return result } @@ -4050,16 +4106,19 @@ def getChanges(mapA, mapB, headstr, objType=null) { String[] leftKeys = left.keySet() String[] rightKeys = right.keySet() leftKeys.each { - // if ( (left[it] instanceof List) || (left[it] instanceof ArrayList) || (left[it] instanceof Map)) { - // // May detect matching items here if sort of objects is problem - // //whatChanged( left[it], right[it], "${headstr}/${it}" ) - // } else { + //if ( (left[it] instanceof List) || (left[it] instanceof ArrayList) || (left[it] instanceof Map)) { + if ( left[it] instanceof Map ) { + def chgs = getChanges( left[it], right[it], "${headstr}/${it}", objType ) + if(chgs && objType) { + itemsChgd += chgs + } + } else { if (left[it].toString() != right[it].toString()) { if(objType) { itemsChgd.push(it.toString()) } } - // } + } } if(itemsChgd.size()) { return itemsChgd } } @@ -4073,7 +4132,7 @@ def whatChanged(mapA, mapB, headstr) { def right = t1 if(left == null || right == null) { - LogAction("Object: $headstr NULL", "trace", true) + LogAction("Object: $headstr NULL", "trace", true) return false } @@ -4126,24 +4185,29 @@ def updateChildData(force = false) { def nforce = atomicState?.forceChildUpd atomicState.forceChildUpd = true try { - atomicState?.lastChildUpdDt = getDtNow() + updTimestampMap("lastChildUpdDt", getDtNow()) + if(force || nforce) { + updTimestampMap("lastChildForceUpdDt", getDtNow()) + } def useMt = !useMilitaryTime ? false : true def dbg = !childDebug ? false : true def logNamePrefix = (settings?.debugAppendAppName || settings?.debugAppendAppName == null) ? true : false - def remDiag = (atomicState?.appData?.database?.allowRemoteDiag && atomicState?.enRemDiagLogging) ? true: false + def remDiag = (atomicState?.enRemDiagLogging && settings?.enRemDiagLogging) ? true: false def nestTz = getNestTimeZone()?.toString() - def api = !apiIssues() ? false : true - def htmlInfo = getHtmlInfo() + def api = apiIssueType() def mobClientType = settings?.mobileClientType def vRprtPrefs = getVoiceRprtPrefs() - def clientBl = atomicState?.clientBlacklisted == true ? true : false - def hcCamTimeout = atomicState?.appData?.healthcheck?.camTimeout ?: 120 - def hcProtWireTimeout = atomicState?.appData?.healthcheck?.protWireTimeout ?: 35 - def hcProtBattTimeout = atomicState?.appData?.healthcheck?.protBattTimeout ?: 1500 - def hcTstatTimeout = atomicState?.appData?.healthcheck?.tstatTimeout ?: 35 - def hcLongTimeout = atomicState?.appData?.healthcheck?.longTimeout ?: 120 - def hcRepairEnabled = atomicState?.appData?.healthcheck?.repairEnabled != false ? true : false + def clientBl = atomicState?.cltBlacklisted == true ? true : false + def hcCamTimeout = atomicState?.appData?.settings?.healthcheck?.camTimeout ?: 120 + def hcProtWireTimeout = atomicState?.appData?.settings?.healthcheck?.protWireTimeout ?: 45 + def hcProtBattTimeout = atomicState?.appData?.settings?.healthcheck?.protBattTimeout ?: 1500 + def hcTstatTimeout = atomicState?.appData?.settings?.healthcheck?.tstatTimeout ?: 45 + def hcLongTimeout = atomicState?.appData?.settings?.healthcheck?.longTimeout ?: 120 + def hcRepairEnabled = atomicState?.appData?.settings?.healthcheck?.repairEnabled != false ? true : false def locPresence = getLocationPresence() + def locSecurityState = getSecurityState() + def locEtaBegin = getEtaBegin() + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } def nPrefs = atomicState?.notificationPrefs def devBannerData = atomicState?.devBannerData ?: null def streamingActive = atomicState?.restStreamingOn == true ? true : false @@ -4152,26 +4216,26 @@ def updateChildData(force = false) { def curWeatherData = [:] if(atomicState?.thermostats && getWeatherDeviceInst()) { - def cur = getWData() + def cur = getWeatherData("curWeather") if(cur) { - curWeatherData["temp"] = getTemperatureScale() == "C" ? (cur?.current_observation?.temp_c ? Math.round(cur?.current_observation?.temp_c.toDouble()) : null) : (cur?.current_observation?.temp_f ? Math.round(cur?.current_observation?.temp_f).toInteger() : null) - curWeatherData["hum"] = cur?.current_observation?.relative_humidity ?: 0 + curWeatherData["temp"] = cur?.temperature ?: null + curWeatherData["hum"] = cur?.relativeHumidity ?: 0 } } def showGraphs = settings?.tstatShowHistoryGraph == false ? false : true - showGraphs = showGraphs && !inReview() ? true : false if(settings?.devNameOverride == null || atomicState?.devNameOverride == null) { // Upgrade force to on atomicState?.devNameOverride = true; settingUpdate("devNameOverride", "true", "bool") } def overRideNames = (atomicState?.devNameOverride) ? true : false - + //def devCodeIds = atomicState?.devCodeIdData ?: [:] def devices = app.getChildDevices(true) devices?.each { if(atomicState?.pollBlocked) { return true } def devId = it?.deviceNetworkId if(devId && atomicState?.thermostats && atomicState?.deviceData?.thermostats && atomicState?.deviceData?.thermostats[devId]) { + //devCodeIds["tstat"] = it?.getDevTypeId() def defmin = fixTempSetting(atomicState?."${devId}_safety_temp_min" ?: null) def defmax = fixTempSetting(atomicState?."${devId}_safety_temp_max" ?: null) def safetyTemps = [ "min":defmin, "max":defmax ] @@ -4181,12 +4245,20 @@ def updateChildData(force = false) { comfortDewpoint = fixTempSetting(settings?.locDesiredComfortDewpointMax ?: null) } def comfortHumidity = settings?."${devId}_comfort_humidity_max" ?: 80 - def autoSchedData = reqSchedInfoRprt(it, false) as Map + if(nforce) { + atomicState?."oldTstatSchedData${devId}" = null + } + def oldTstatSchedData = atomicState?."oldTstatSchedData${devId}" + if(oldTstatSchedData == null) { + oldTstatSchedData = reqSchedInfoRprt(it, false) as Map + atomicState?."oldTstatSchedData${devId}" = oldTstatSchedData + } + def autoSchedData = oldTstatSchedData as Map def tData = ["data":atomicState?.deviceData?.thermostats[devId], "mt":useMt, "debug":dbg, "tz":nestTz, "apiIssues":api, "safetyTemps":safetyTemps, "comfortHumidity":comfortHumidity, - "comfortDewpoint":comfortDewpoint, "pres":locPresence, "childWaitVal":getChildWaitVal().toInteger(), "htmlInfo":htmlInfo, "allowDbException":allowDbException, + "comfortDewpoint":comfortDewpoint, "pres":locPresence, "childWaitVal":getChildWaitVal().toInteger(), "allowDbException":allowDbException, "latestVer":latestTstatVer()?.ver?.toString(), "vReportPrefs":vRprtPrefs, "clientBl":clientBl, "curWeatherData":curWeatherData, "logPrefix":logNamePrefix, "hcTimeout":hcTstatTimeout, - "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "autoSchedData":autoSchedData, "healthNotify":nPrefs?.dev?.devHealth?.healthMsg, "showGraphs":showGraphs, - "devBannerData":devBannerData, "restStreaming":streamingActive, "isBeta":isBeta, "hcRepairEnabled":hcRepairEnabled] + "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "autoSchedData":autoSchedData, "healthNotify":nPrefs?.dev?.devHealth, "showGraphs":showGraphs, + "devBannerData":devBannerData, "restStreaming":streamingActive, "isBeta":isBeta, "hcRepairEnabled":hcRepairEnabled, "etaBegin":locEtaBegin ] def oldTstatData = atomicState?."oldTstatData${devId}" def tDataChecksum = generateMD5_A(tData.toString()) atomicState."oldTstatData${devId}" = tDataChecksum @@ -4199,8 +4271,7 @@ def updateChildData(force = false) { atomicState?.swVer = sData if(sData?.tDevVer != "" && (versionStr2Int(sData?.tDevVer) >= minVersions()?.thermostat?.val)) { //LogTrace("UpdateChildData >> Thermostat id: ${devId} | data: ${tData}") - LogTrace("updateChildData >> Thermostat id: ${devId} | oldTstatData: ${oldTstatData} tDataChecksum: ${tDataChecksum} force: $force nforce: $nforce") - it?.generateEvent(tData) + LogTrace("updateChildData >> Thermostat id: ${devId} | oldTstatData: ${oldTstatData} tDataChecksum: ${tDataChecksum} force: $force nforce: $nforce") if(atomicState?."lastUpdated${devId}Dt" != null) { state.remove("lastUpdated${devId}Dt" as String) } } else { if(atomicState?."lastUpdated${devId}Dt" == null) { @@ -4209,15 +4280,16 @@ def updateChildData(force = false) { LogAction("NST THERMOSTAT DEVICE UPDATE REQUIRED: Thermostat ${devId} (v${sData?.tDevVer}) | REQUIRED: (v${minVersions()?.thermostat?.desc}) | Update the Device code to the latest software in the IDE", "error", true) appUpdateNotify() } - it?.generateEvent(tData) } + it?.generateEvent(tData) } return true } else if(devId && atomicState?.protects && atomicState?.deviceData?.smoke_co_alarms && atomicState?.deviceData?.smoke_co_alarms[devId]) { + //devCodeIds["protect"] = it?.getDevTypeId() def pData = ["data":atomicState?.deviceData?.smoke_co_alarms[devId], "mt":useMt, "debug":dbg, "showProtActEvts":(!showProtActEvts ? false : true), "logPrefix":logNamePrefix, - "tz":nestTz, "htmlInfo":htmlInfo, "apiIssues":api, "allowDbException":allowDbException, "latestVer":latestProtVer()?.ver?.toString(), "clientBl":clientBl, - "hcWireTimeout":hcProtWireTimeout, "hcBattTimeout":hcProtBattTimeout, "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "healthNotify":nPrefs?.dev?.devHealth?.healthMsg, + "tz":nestTz, "apiIssues":api, "allowDbException":allowDbException, "latestVer":latestProtVer()?.ver?.toString(), "clientBl":clientBl, + "hcWireTimeout":hcProtWireTimeout, "hcBattTimeout":hcProtBattTimeout, "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "healthNotify":nPrefs?.dev?.devHealth, "devBannerData":devBannerData, "restStreaming":streamingActive, "isBeta":isBeta, "hcRepairEnabled":hcRepairEnabled ] def oldProtData = atomicState?."oldProtData${devId}" def pDataChecksum = generateMD5_A(pData.toString()) @@ -4231,8 +4303,7 @@ def updateChildData(force = false) { atomicState?.swVer = sData if(sData?.pDevVer != "" && (versionStr2Int(sData?.pDevVer) >= minVersions()?.protect?.val)) { //LogTrace("UpdateChildData >> Protect id: ${devId} | data: ${pData}") - LogTrace("UpdateChildData >> Protect id: ${devId} | oldProtData: ${oldProtData} pDataChecksum: ${pDataChecksum} force: $force nforce: $nforce") - it?.generateEvent(pData) + LogTrace("UpdateChildData >> Protect id: ${devId} | oldProtData: ${oldProtData} pDataChecksum: ${pDataChecksum} force: $force nforce: $nforce") if(atomicState?."lastUpdated${devId}Dt" != null) { state.remove("lastUpdated${devId}Dt" as String) } } else { if(atomicState?."lastUpdated${devId}Dt" == null) { @@ -4241,17 +4312,19 @@ def updateChildData(force = false) { LogAction("NST PROTECT DEVICE UPDATE REQUIRED: Protect ${devId} (v${sData?.pDevVer}) | REQUIRED: (v${minVersions()?.protect?.desc}) | Update the Device code to the latest software in the IDE", "error", true) appUpdateNotify() } - it?.generateEvent(pData) } + it?.generateEvent(pData) } return true } else if(devId && atomicState?.cameras && atomicState?.deviceData?.cameras && atomicState?.deviceData?.cameras[devId]) { - def camData = ["data":atomicState?.deviceData?.cameras[devId], "mt":useMt, "debug":dbg, "logPrefix":logNamePrefix, - "tz":nestTz, "htmlInfo":htmlInfo, "apiIssues":api, "allowDbException":allowDbException, "latestVer":latestCamVer()?.ver?.toString(), "clientBl":clientBl, - "hcTimeout":hcCamTimeout, "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "healthNotify":nPrefs?.dev?.devHealth?.healthMsg, + //devCodeIds["camera"] = it?.getDevTypeId() + List camMotionZones = (settings?.camEnMotionZoneFltr && settings?."camera_${devId}_zones"?.size()) ? settings?."camera_${devId}_zones" : [] + def camData = ["data":atomicState?.deviceData?.cameras[devId], "mt":useMt, "debug":dbg, "logPrefix":logNamePrefix, "camMotionZones": camMotionZones, + "tz":nestTz, "apiIssues":api, "allowDbException":allowDbException, "latestVer":latestCamVer()?.ver?.toString(), "clientBl":clientBl, + "hcTimeout":hcCamTimeout, "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "healthNotify":nPrefs?.dev?.devHealth, "streamNotify":nPrefs?.dev?.camera?.streamMsg, "devBannerData":devBannerData, "restStreaming":streamingActive, "motionSndChgWaitVal":motionSndChgWaitVal, - "isBeta":isBeta, "camTakeSnapOnEvt": camTakeSnapOnEvt, "hcRepairEnabled":hcRepairEnabled ] + "isBeta":isBeta, "camTakeSnapOnEvt": camTakeSnapOnEvt, "hcRepairEnabled":hcRepairEnabled, "secState":locSecurityState ] def oldCamData = atomicState?."oldCamData${devId}" def cDataChecksum = generateMD5_A(camData.toString()) atomicState."oldCamData${devId}" = cDataChecksum @@ -4263,9 +4336,8 @@ def updateChildData(force = false) { sData["camDevVer"] = t1 ?: "" atomicState?.swVer = sData if(sData?.camDevVer != "" && (versionStr2Int(sData?.camDevVer) >= minVersions()?.camera?.val)) { - //LogTrace("UpdateChildData >> Camera id: ${devId} | data: ${camData}") - LogTrace("UpdateChildData >> Camera id: ${devId} | oldCamData: ${oldCamData} cDataChecksum: ${cDataChecksum} force: $force nforce: $nforce") - it?.generateEvent(camData) + // LogTrace("UpdateChildData >> Camera id: ${devId} | data: ${camData}") + LogTrace("UpdateChildData >> Camera id: ${devId} | oldCamData: ${oldCamData} cDataChecksum: ${cDataChecksum} force: $force nforce: $nforce") if(atomicState?."lastUpdated${devId}Dt" != null) { state.remove("lastUpdated${devId}Dt" as String) } } else { if(atomicState?."lastUpdated${devId}Dt" == null) { @@ -4274,15 +4346,16 @@ def updateChildData(force = false) { LogAction("NST CAMERA DEVICE UPDATE REQUIRED: Camera ${devId} (v${sData?.camDevVer}) | REQUIRED: (v${minVersions()?.camera?.desc}) | Update the Device code to the latest software in the IDE", "error", true) appUpdateNotify() } - it?.generateEvent(camData) } + it?.generateEvent(camData) } return true } else if(devId && atomicState?.presDevice && devId == getNestPresId()) { + //devCodeIds["presence"] = it?.getDevTypeId() def pData = ["debug":dbg, "logPrefix":logNamePrefix, "tz":nestTz, "mt":useMt, "pres":locPresence, "apiIssues":api, "allowDbException":allowDbException, "latestVer":latestPresVer()?.ver?.toString(), "clientBl":clientBl, "hcTimeout":hcLongTimeout, "mobileClientType":mobClientType, "hcRepairEnabled":hcRepairEnabled, - "enRemDiagLogging":remDiag, "healthNotify":nPrefs?.dev?.devHealth?.healthMsg, "lastStrucDataUpd": atomicState?.lastStrucDataUpd, "isBeta":isBeta ] + "enRemDiagLogging":remDiag, "healthNotify":nPrefs?.dev?.devHealth, "lastStrDataUpd": getTimestampVal("lastStrDataUpd"), "isBeta":isBeta ] def oldPresData = atomicState?."oldPresData${devId}" def pDataChecksum = generateMD5_A(pData.toString()) atomicState."oldPresData${devId}" = pDataChecksum @@ -4294,8 +4367,7 @@ def updateChildData(force = false) { sData["presDevVer"] = t1 ?: "" atomicState?.swVer = sData if(sData?.presDevVer != "" && (versionStr2Int(sData?.presDevVer) >= minVersions()?.presence?.val)) { - LogTrace("UpdateChildData >> Presence id: ${devId} | oldPresData: ${oldPresData} pDataChecksum: ${pDataChecksum} force: $force nforce: $nforce") - it?.generateEvent(pData) + LogTrace("UpdateChildData >> Presence id: ${devId} | oldPresData: ${oldPresData} pDataChecksum: ${pDataChecksum} force: $force nforce: $nforce") if(atomicState?."lastUpdated${devId}Dt" != null) { state.remove("lastUpdated${devId}Dt" as String) } } else { if(atomicState?."lastUpdated${devId}Dt" == null) { @@ -4304,17 +4376,18 @@ def updateChildData(force = false) { LogAction("NST PRESENCE DEVICE UPDATE REQUIRED: Presence ${devId} (v${sData?.presDevVer}) | REQUIRED: (v${minVersions()?.presence?.desc}) | Update the Device code to the latest software in the IDE", "error", true) appUpdateNotify() } - it?.generateEvent(pData) } + it?.generateEvent(pData) } return true } else if(devId && atomicState?.weatherDevice && devId == getNestWeatherId()) { - def wData1 = ["weatCond":getWData(), "weatForecast":getWForecastData(), "weatAstronomy":getWAstronomyData(), "weatAlerts":getWAlertsData()] - def wData = ["data":wData1, "tz":nestTz, "mt":useMt, "debug":dbg, "logPrefix":logNamePrefix, "apiIssues":api, "htmlInfo":htmlInfo, + //devCodeIds["weather"] = it?.getDevTypeId() + def wData1 = ["weatCond":getWeatherData("curWeather"), "weatForecast":getWeatherData("curForecast"), /* "weatAstronomy":getWeatherData("curAstronomy"),*/ "weatAlerts":getWeatherData("curAlerts"), weatLocation:getWeatherData("curLocation")] + def wData = ["data":wData1, "tz":nestTz, "mt":useMt, "debug":dbg, "logPrefix":logNamePrefix, "apiIssues":api, "allowDbException":allowDbException, "weathAlertNotif":settings?.weathAlertNotif, "latestVer":latestWeathVer()?.ver?.toString(), "clientBl":clientBl, "hcTimeout":hcLongTimeout, "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "hcRepairEnabled":hcRepairEnabled, - "healthNotify":nPrefs?.dev?.devHealth?.healthMsg, "showGraphs":showGraphs, "devBannerData":devBannerData, "isBeta":isBeta ] + "healthNotify":nPrefs?.dev?.devHealth, "showGraphs":showGraphs, "devBannerData":devBannerData, "isBeta":isBeta ] def oldWeatherData = atomicState?."oldWeatherData${devId}" def wDataChecksum = generateMD5_A(wData.toString()) def showWGraphs = settings?.weatherShowGraph == false ? false : true @@ -4327,8 +4400,7 @@ def updateChildData(force = false) { sData["weatDevVer"] = t1 ?: "" atomicState?.swVer = sData if(sData?.weatDevVer != "" && (versionStr2Int(sData?.weatDevVer) >= minVersions()?.weather?.val)) { - LogTrace("UpdateChildData >> Weather id: ${devId} oldWeatherData: ${oldWeatherData} wDataChecksum: ${wDataChecksum} force: $force nforce: $nforce") - it?.generateEvent(wData) + LogTrace("UpdateChildData >> Weather id: ${devId} oldWeatherData: ${oldWeatherData} wDataChecksum: ${wDataChecksum} force: $force nforce: $nforce") if(atomicState?."lastUpdated${devId}Dt" != null) { state.remove("lastUpdated${devId}Dt" as String) } } else { if(atomicState?."lastUpdated${devId}Dt" == null) { @@ -4337,17 +4409,16 @@ def updateChildData(force = false) { LogAction("NST WEATHER DEVICE UPDATE REQUIRED: Weather ${devId} (v${sData?.weatDevVer}) | REQUIRED: (v${minVersions()?.weather?.desc}) | Update the Device code to the latest software in the IDE", "error", true) appUpdateNotify() } - it?.generateEvent(wData) } + it?.generateEvent(wData) } return true } - else if(devId && atomicState?.vThermostats && atomicState?."vThermostat${devId}") { def physdevId = atomicState?."vThermostatMirrorId${devId}" - if(physdevId && atomicState?.thermostats && atomicState?.deviceData?.thermostats && atomicState?.deviceData?.thermostats[physdevId]) { - def data = atomicState?.deviceData?.thermostats[physdevId] + def tmp_data = atomicState?.deviceData?.thermostats[physdevId] + def data = tmp_data def defmin = fixTempSetting(atomicState?."${physdevId}_safety_temp_min" ?: null) def defmax = fixTempSetting(atomicState?."${physdevId}_safety_temp_max" ?: null) def safetyTemps = [ "min":defmin, "max":defmax ] @@ -4358,14 +4429,16 @@ def updateChildData(force = false) { def comfortHumidity = settings?."${physdevId}_comfort_humidity_max" ?: 80 def automationChildApp = getChildApps().find{ it.id == atomicState?."vThermostatChildAppId${devId}" } if(automationChildApp != null && !automationChildApp.getIsAutomationDisabled()) { + //data = new JsonSlurper().parseText(JsonOutput.toJson(tmp_data)) // This is a deep clone as object is same reference + data = [:] + tmp_data def tempC = 0.0 - def tempF = 0 + def tempF = 0.0 if(getTemperatureScale() == "C") { tempC = automationChildApp.getRemoteSenTemp() - tempF = (tempC * (9 / 5) + 32) as Integer // + tempF = (tempC * (9 / 5) + 32.0) } else { tempF = automationChildApp.getRemoteSenTemp() - tempC = (tempF - 32) * (5 / 9) as Double // + tempC = (tempF - 32.0) * (5 / 9) as Double } data?.ambient_temperature_c = tempC data?.ambient_temperature_f = tempF @@ -4374,20 +4447,20 @@ def updateChildData(force = false) { def ctempF = 0 if(getTemperatureScale() == "C") { ctempC = automationChildApp.getRemSenCoolSetTemp() - ctempF = ctempC != null ? (ctempC * (9 / 5) + 32.0) as Integer : null // + ctempF = ctempC != null ? (ctempC * (9 / 5) + 32.0) as Integer : null } else { ctempF = automationChildApp.getRemSenCoolSetTemp() - ctempC = ctempF != null ? (ctempF - 32.0) * (5 / 9) as Double : null // + ctempC = ctempF != null ? (ctempF - 32.0) * (5 / 9) as Double : null } def htempC = 0.0 def htempF = 0 if(getTemperatureScale() == "C") { htempC = automationChildApp.getRemSenHeatSetTemp() - htempF = htempC != null ? (htempC * (9 / 5) + 32.0) as Integer : null // + htempF = htempC != null ? (htempC * (9 / 5) + 32.0) as Integer : null } else { htempF = automationChildApp.getRemSenHeatSetTemp() - htempC = htempF != null ? (htempF - 32.0) * (5 / 9) as Double : null // + htempC = htempF != null ? (htempF - 32.0) * (5 / 9) as Double : null } if(data?.hvac_mode.toString() == "heat-cool") { @@ -4404,11 +4477,20 @@ def updateChildData(force = false) { } } - def autoSchedData = reqSchedInfoRprt(it, false) as Map - def tData = ["data":data, "mt":useMt, "debug":dbg, "tz":nestTz, "apiIssues":api, "safetyTemps":safetyTemps, "comfortHumidity":comfortHumidity, "hcRepairEnabled":hcRepairEnabled, - "comfortDewpoint":comfortDewpoint, "pres":locPresence, "childWaitVal":getChildWaitVal().toInteger(), "htmlInfo":htmlInfo, "allowDbException":allowDbException, + if(nforce) { + atomicState?."oldvTstatSchedData${devId}" = null + } + def oldTstatSchedData = atomicState?."oldvTstatSchedData${devId}" + if(oldTstatSchedData == null) { + oldTstatSchedData = reqSchedInfoRprt(it, false) as Map + atomicState?."oldvTstatSchedData${devId}" = oldTstatSchedData + } + def autoSchedData = oldTstatSchedData as Map + def tData = ["data":data, "mt":useMt, "debug":dbg, "tz":nestTz, "apiIssues":api, "safetyTemps":safetyTemps, "comfortHumidity":comfortHumidity, + "comfortDewpoint":comfortDewpoint, "pres":locPresence, "childWaitVal":getChildWaitVal().toInteger(), "allowDbException":allowDbException, "latestVer":latestvStatVer()?.ver?.toString(), "vReportPrefs":vRprtPrefs, "clientBl":clientBl, "curWeatherData":curWeatherData, "logPrefix":logNamePrefix, "hcTimeout":hcTstatTimeout, - "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "autoSchedData":autoSchedData, "healthNotify":nPrefs?.dev?.devHealth?.healthMsg, "showGraphs":showGraphs, "devBannerData":devBannerData, "isBeta":isBeta] + "mobileClientType":mobClientType, "enRemDiagLogging":remDiag, "autoSchedData":autoSchedData, "healthNotify":nPrefs?.dev?.devHealth, "showGraphs":showGraphs, + "devBannerData":devBannerData, "restStreaming":streamingActive, "isBeta":isBeta, "hcRepairEnabled":hcRepairEnabled, "etaBegin":locEtaBegin ] def oldTstatData = atomicState?."oldvStatData${devId}" def tDataChecksum = generateMD5_A(tData.toString()) @@ -4421,8 +4503,7 @@ def updateChildData(force = false) { sData["vtDevVer"] = t1 ?: "" atomicState?.swVer = sData if(sData?.vtDevVer != "" && (versionStr2Int(sData?.vtDevVer) >= minVersions()?.thermostat?.val)) { - LogTrace("UpdateChildData >> vThermostat id: ${devId} | oldvStatData: ${oldvStatData} tDataChecksum: ${tDataChecksum} force: $force nforce: $nforce") - it?.generateEvent(tData) + LogTrace("UpdateChildData >> vThermostat id: ${devId} | oldvStatData: ${oldvStatData} tDataChecksum: ${tDataChecksum} force: $force nforce: $nforce") if(atomicState?."lastUpdated${devId}Dt" != null) { state.remove("lastUpdated${devId}Dt" as String) } } else { if(atomicState?."lastUpdated${devId}Dt" == null) { @@ -4430,8 +4511,8 @@ def updateChildData(force = false) { } else { LogAction("NST THERMOSTAT DEVICE UPDATE REQUIRED: Thermostat ${devId} (v${sData?.vtDevVer}) | REQUIRED: (v${minVersions()?.thermostat?.desc}) | Update the Device code to the latest software in the IDE", "error", true) } - it?.generateEvent(tData) } + it?.generateEvent(tData) } return true } @@ -4454,11 +4535,13 @@ def updateChildData(force = false) { return true } } + //atomicState?.devCodeIdData = devCodeIds } catch (ex) { log.error "updateChildData Exception:", ex sendExceptionData(ex, "updateChildData") - atomicState?.lastChildUpdDt = null + updTimestampMap("lastChildUpdDt", null) + updTimestampMap("lastChildForceUpdDt", null) return } if(atomicState?.pollBlocked) { return } @@ -4471,7 +4554,7 @@ def setNeedChildUpdate() { } def tUnitStr() { - return "°${getTemperatureScale()}" + return "\u00b0${getTemperatureScale()}" } def setDeviceLabel(devId, labelStr) { @@ -4492,7 +4575,7 @@ void physDevLblHandler(devType, devId, devLbl, devStateName, apiName, abrevStr, def curlbl = devLbl?.toString() if(deflbl && deflbl == curlbl) { nameIsDefault = true } def newlbl = "getNest${abrevStr.capitalize()}Label"(apiName, devId) - LogTrace("physDevLblHandler | deflbl: ${deflbl} | curlbl: ${curlbl} | newlbl: ${newlbl} | deflblval: ${deflblval} || devId: ${devId}") + //LogTrace("physDevLblHandler | deflbl: ${deflbl} | curlbl: ${curlbl} | newlbl: ${newlbl} | deflblval: ${deflblval} || devId: ${devId}") if(ovrRideNames || (nameIsDefault && curlbl != newlbl)) { // label change from nest if(curlbl != newlbl) { LogAction("Changing name from ${curlbl} to ${newlbl}", "info", true) @@ -4506,14 +4589,14 @@ void physDevLblHandler(devType, devId, devLbl, devStateName, apiName, abrevStr, if(atomicState?.custLabelUsed && settings?."${abrevStr}_${devId}_lbl" != curlbl) { settingUpdate("${abrevStr}_${devId}_lbl", curlbl?.toString()) } - if(!atomicState?.custLabelUsed && settings?."${abrevStr}_${devId}_lbl") { settingUpdate("${abrevStr}_${devId}_lbl", "") } - if(settings?."${abrevStr}_${deflblval}_lbl") { settingUpdate("${abrevStr}_${deflblval}_lbl", "") } // clean up old stuff + if(!atomicState?.custLabelUsed && settings?."${abrevStr}_${devId}_lbl") { settingRemove("${abrevStr}_${devId}_lbl") } + if(settings?."${abrevStr}_${deflblval}_lbl") { settingRemove("${abrevStr}_${deflblval}_lbl") } // clean up old stuff } void virtDevLblHandler(devId, devLbl, devMethAbrev, abrevStr, ovrRideNames) { def curlbl = devLbl?.toString() def newlbl = "getNest${devMethAbrev.capitalize()}Label"() - LogTrace("virtDevLblHandler | curlbl: ${curlbl} | newlbl: ${newlbl} || devId: ${devId}") + //LogTrace("virtDevLblHandler | curlbl: ${curlbl} | newlbl: ${newlbl} || devId: ${devId}") if(ovrRideNames && curlbl != newlbl) { LogAction("Changing name from ${curlbl} to ${newlbl}", "info", true) setDeviceLabel(devId, newlbl?.toString()) @@ -4522,28 +4605,30 @@ void virtDevLblHandler(devId, devLbl, devMethAbrev, abrevStr, ovrRideNames) { if(atomicState?.custLabelUsed && settings?."${abrevStr}Dev_lbl" != curlbl) { settingUpdate("${abrevStr}Dev_lbl", curlbl?.toString()) } - if(!atomicState?.custLabelUsed && settings?."${abrevStr}Dev_lbl") { settingUpdate("${abrevStr}Dev_lbl", "") } + if(!atomicState?.custLabelUsed && settings?."${abrevStr}Dev_lbl") { settingRemove("${abrevStr}Dev_lbl") } } def apiIssues() { def t0 = atomicState?.apiIssuesList ?: [false, false, false, false, false, false, false] - def result = t0[3..-1].every { it == true } ? true : false - def dt = atomicState?.apiIssueDt + atomicState?.apiIssuesList = t0 + def result = t0[5..-1].every { it == true } ? true : false + def dt = getTimestampVal("apiIssueDt") if(result) { - LogAction("Nest API Issues ${dt ? "may still be occurring. Status will clear when last updates are good (Last Updates: ${t0}) | Issues began at ($dt) " : "Detected (${getDtNow()})"}", "warn", true) + def str = dt ? "may still be occurring. Status will clear when last updates are good (Last Updates: ${t0}) | Issues began at ($dt) " : "Detected (${getDtNow()})" + LogAction("Nest API Issues ${str}", "warn", true) } - apiIssueType() - atomicState?.apiIssueDt = (result ? (dt ?: getDtNow()) : null) return result } def apiIssueType() { - def res = "none" + def res = "Good" //this looks at the last 3 items added and determines whether issue is sporadic or outage - def t0 = atomicState?.apiIssuesList ?: [false, false, false, false, false, false, false] + def t0 = [] + t0 = atomicState?.apiIssuesList ?: [false, false, false, false, false, false, false] + atomicState?.apiIssuesList = t0 def items = t0[3..-1].findAll { it == true } - if(items?.size() >= 1 && items?.size() <= 2) { res = "sporadic" } - else if(items?.size() >= 3) { res = "outage" } + if(items?.size() >= 1 && items?.size() <= 2) { res = "Sporadic" } + else if(items?.size() >= 3) { res = "Outage" } //log.debug "apiIssueType: $res" return res } @@ -4567,54 +4652,96 @@ def apiIssueEvent(issue, cmd = null) { nList?.push(issue) list = nList } - if(list) { atomicState?.apiIssuesList = list } + atomicState?.apiIssuesList = list + if(issue) { + if(!getTimestampVal("apiIssueDt")) { + updTimestampMap("apiIssueDt", getDtNow()) + } + } else { + def result = list[3..-1].every { it == false } + def rateLimit = (atomicState?.apiRateLimited) ? true : false + if(rateLimit) { + def t0 = atomicState?.apiCmdFailData?.dt ? GetTimeDiffSeconds(atomicState?.apiCmdFailData?.dt, null, "apiIssueEvent").toInteger() : 200 + if((t0 > 120 && result) || t0 > 300) { + atomicState?.apiRateLimited = false + rateLimit = false + LogAction("Clearing rate Limit", "info", true) + } + } + } } def ok2PollMetaData() { +/* if(!atomicState?.authToken) { return false } + if(!atomicState.metaData) { return true } if(atomicState?.pollBlocked) { return false } if(atomicState?.needMetaPoll) { return true } def pollTime = !settings?.pollMetaValue ? (3600 * 4) : settings?.pollMetaValue.toInteger() - def val = pollTime / 3 // + def val = pollTime / 3 if(val > 60) { val = 50 } return ( ((getLastMetaPollSec() + val) > pollTime) ? true : false ) +*/ + def pollTime = !settings?.pollMetaValue ? (3600 * 4) : settings?.pollMetaValue.toInteger() + return (pollOk("Meta", pollTime, "metaData")) ? true : false } def ok2PollDevice() { +/* if(!atomicState?.authToken) { return false } + if(!atomicState?.deviceData) { return true } if(atomicState?.pollBlocked) { return false } if(atomicState?.needDevPoll) { return true } def pollTime = !settings?.pollValue ? 180 : settings?.pollValue.toInteger() - def val = pollTime / 3 // + def val = pollTime / 3 val = Math.max(Math.min(val.toInteger(), 50),25) //if(val > 60) { val = 50 } - return ( ((getLastDevicePollSec() + val) > pollTime) ? true : false ) + return ( ((getLastDevPollSec() + val) > pollTime) ? true : false ) +*/ + def pollTime = !settings?.pollValue ? 180 : settings?.pollValue.toInteger() + return (pollOk("Dev", pollTime, "deviceData")) ? true : false } def ok2PollStruct() { +/* if(!atomicState?.authToken) { return false } + if(!atomicState?.structData) { return true } if(atomicState?.pollBlocked) { return false } if(atomicState?.needStrPoll) { return true } def pollStrTime = !settings?.pollStrValue ? 180 : settings?.pollStrValue.toInteger() - def val = pollStrTime / 3 // + def val = pollStrTime / 3 val = Math.max(Math.min(val.toInteger(), 50),25) //if(val > 60) { val = 50 } - return ( ((getLastStructPollSec() + val) > pollStrTime || !atomicState?.structData) ? true : false ) + return ( ((getLastStrPollSec() + val) > pollStrTime) ? true : false ) +*/ + def pollStrTime = !settings?.pollStrValue ? 180 : settings?.pollStrValue.toInteger() + return (pollOk("Str", pollStrTime, "structData")) ? true : false } +def pollOk(typ, pTime, stVar) { + if(!atomicState?.authToken) { return false } + if(!atomicState?."${stVar}") { return true } + if(atomicState?.pollBlocked) { return false } + if(atomicState?."need${typ}Poll") { return true } + def pollTime = pTime as Integer + def val = pollTime / 3 + val = Math.max(Math.min(val.toInteger(), 50),25) + return ( (("getLast${typ}PollSec"() + val) > pollTime) ? true : false ) +} def isPollAllowed() { return (atomicState?.pollingOn && atomicState?.authToken && - !atomicState?.clientBlacklisted && + !atomicState?.cltBlacklisted && (atomicState?.thermostats || atomicState?.protects || atomicState?.weatherDevice || atomicState?.cameras)) ? true : false } -def getLastMetaPollSec() { return !atomicState?.lastMetaDataUpd ? 100000 : GetTimeDiffSeconds(atomicState?.lastMetaDataUpd, null, "getLastMetaPollSec").toInteger() } -def getLastDevicePollSec() { return !atomicState?.lastDevDataUpd ? 840 : GetTimeDiffSeconds(atomicState?.lastDevDataUpd, null, "getLastDevicePollSec").toInteger() } -def getLastStructPollSec() { return !atomicState?.lastStrucDataUpd ? 1000 : GetTimeDiffSeconds(atomicState?.lastStrucDataUpd, null, "getLastStructPollSec").toInteger() } -def getLastForcedPollSec() { return !atomicState?.lastForcePoll ? 1000 : GetTimeDiffSeconds(atomicState?.lastForcePoll, null, "getLastForcedPollSec").toInteger() } -def getLastChildUpdSec() { return !atomicState?.lastChildUpdDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastChildUpdDt, null, "getLastChildUpdSec").toInteger() } -def getLastHeardFromNestSec() { return !atomicState?.lastHeardFromNestDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastHeardFromNestDt, null, "getLastHeardFromNestSec").toInteger() } +def getLastMetaPollSec() { return getTimeSeconds("lastMetaDataUpd", 100000, "getLastMetaPollSec").toInteger() } +def getLastDevPollSec() { return getTimeSeconds("lastDevDataUpd", 840, "getLastDevPollSec").toInteger() } +def getLastStrPollSec() { return getTimeSeconds("lastStrDataUpd", 1000, "getLastStrPollSec").toInteger() } +def getLastForcedPollSec() { return getTimeSeconds("lastForcePoll", 1000, "getLastForcedPollSec").toInteger() } +def getLastChildUpdSec() { return getTimeSeconds("lastChildUpdDt", 100000, "getLastChildUpdSec").toInteger() } +def getLastChildForceUpdSec() { return getTimeSeconds("lastChildForceUpdDt", 100000, "getLastChildForceUpdSec").toInteger() } +def getLastHeardFromNestSec() { return getTimeSeconds("lastHeardFromNestDt", 100000, "getLastHeardFromNestSec").toInteger() } /************************************************************************************************ | Nest API Commands | @@ -4622,7 +4749,7 @@ def getLastHeardFromNestSec() { return !atomicState?.lastHeardFromNestDt ? 10000 private cmdProcState(Boolean value) { atomicState?.cmdIsProc = value } private cmdIsProc() { return (!atomicState?.cmdIsProc) ? false : true } -private getLastProcSeconds() { return atomicState?.cmdLastProcDt ? GetTimeDiffSeconds(atomicState?.cmdLastProcDt, null, "getLastProcSeconds") : 0 } +private getLastProcSeconds() { return getTimeSeconds("cmdLastProcDt", 0, "getLastProcSeconds") } def apiVar() { def api = [ @@ -4633,12 +4760,88 @@ def apiVar() { targetF:"target_temperature_f", targetC:"target_temperature_c", targetLowF:"target_temperature_low_f", setLabel:"label", targetLowC:"target_temperature_low_c", targetHighF:"target_temperature_high_f", targetHighC:"target_temperature_high_c", fanActive:"fan_timer_active", fanTimer:"fan_timer_timeout", fanDuration:"fan_timer_duration", hvacMode:"hvac_mode", - away:"away", streaming:"is_streaming", setTscale:"temperature_scale" + away:"away", streaming:"is_streaming", setTscale:"temperature_scale", eta:"eta" ] ] return api } +// There are 3 different return values +def getPdevId(Boolean virt, devId) { + def pChild + if(virt && atomicState?.vThermostats && devId) { + if(atomicState?."vThermostat${devId}") { + def pdevId = atomicState?."vThermostatMirrorId${devId}" + if(pdevId) { pChild = getChildDevice(pdevId) } + if(pChild) { return pChild } + else { return "00000" } + } + } + return pChild +} + +def setEtaState(child, etaData, virtual=false) { + def devId = !child?.device?.deviceNetworkId ? child?.toString() : child?.device?.deviceNetworkId.toString() + + def str1 = "setEtaState | " + def strAction = "BAD data" + def strArgs = " ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) | Trip_Id: ${etaData?.trip_id} | Begin: ${etaData?.estimated_arrival_window_begin} | End: ${etaData?.estimated_arrival_window_end}" + + if(etaData?.trip_id && etaData?.estimated_arrival_window_begin && etaData?.estimated_arrival_window_end) { + def etaObj = [ "trip_id":"${etaData.trip_id}", "estimated_arrival_window_begin":"${etaData.estimated_arrival_window_begin}", "estimated_arrival_window_end":"${etaData.estimated_arrival_window_end}" ] + // "trip_id":"sample-trip-id","estimated_arrival_window_begin":"2014-10-31T22:42:00.000Z","estimated_arrival_window_end":"2014-10-31T23:59:59.000Z" + // new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC")) + + strAction = "Setting Eta" + def pChild = getPdevId(virtual.toBoolean(), devId) + if(pChild == null) { + LogAction(str1+strAction+strArgs, "debug", true) + return sendNestApiCmd(atomicState?.structures, apiVar().rootTypes.struct, apiVar().cmdObjs.eta, etaObj, devId) + } else { + if(pChild != "00000") { + LogAction(str1+strAction+strArgs, "debug", true) + pChild.setNestEta(etaData?.trip_id, etaData?.estimated_arrival_window_begin, etaData.estimated_arrival_window_end) { + } + return + } else { + strAction = "CANNOT Set Eta" + } + } + } + LogAction(str1+strAction+strArgs, "warn", true) +} + +def cancelEtaState(child, trip_id, virtual=false) { + def devId = !child?.device?.deviceNetworkId ? child?.toString() : child?.device?.deviceNetworkId.toString() + + def str1 = "cancelEtaState | " + def strAction = "BAD data" + def strArgs = " ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) | Trip_Id: ${trip_id}" + + if(trip_id) { + def etaObj = [ "trip_id":"${trip_id}", "estimated_arrival_window_begin":0, "estimated_arrival_window_end":0 ] + // "trip_id":"sample-trip-id","estimated_arrival_window_begin":"2014-10-31T22:42:00.000Z","estimated_arrival_window_end":"2014-10-31T23:59:59.000Z" + // new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC")) + + strAction = "Cancel Eta" + def pChild = getPdevId(virtual.toBoolean(), devId) + if(pChild == null) { + LogAction(str1+strAction+strArgs, "debug", true) + return sendNestApiCmd(atomicState?.structures, apiVar().rootTypes.struct, apiVar().cmdObjs.eta, etaObj, devId) + } else { + if(pChild != "00000") { + LogAction(str1+strAction+strArgs, "debug", true) + pChild.cancelNestEta(trip_id) { + } + return + } else { + strAction = "CANNOT Cancel Eta" + } + } + } + LogAction(str1+strAction+strArgs, "warn", true) +} + def setCamStreaming(child, streamOn) { def devId = !child?.device?.deviceNetworkId ? child?.toString() : child?.device?.deviceNetworkId.toString() def val = streamOn.toBoolean() ? true : false @@ -4646,20 +4849,18 @@ def setCamStreaming(child, streamOn) { return sendNestApiCmd(devId, apiVar().rootTypes.cam, apiVar().cmdObjs.streaming, val, devId) } -def setCamLabel(child, label, virtual=false) { +def setCamLabel(child, label) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() def val = label - def virt = virtual.toBoolean() -// This is not used anywhere. A command to set label is not available in the dth for a callback +// This is not used anywhere. A command to set label is not available in the dth for a callback LogAction("setCamLabel | Setting Camera (${child?.device?.displayName} - ${devId}) Label to (${val})", "debug", true) return sendNestApiCmd(devId, apiVar().rootTypes.cam, apiVar().cmdObjs.setLabel, val, devId) } -def setProtLabel(child, label, virtual=false) { +def setProtLabel(child, label) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() def val = label - def virt = virtual.toBoolean() -// This is not used anywhere. A command to set label is not available in the dth for a callback +// This is not used anywhere. A command to set label is not available in the dth for a callback LogAction("setProtLabel | Setting Protect (${child?.device?.displayName} - ${devId}) Label to (${val})", "debug", true) return sendNestApiCmd(devId, apiVar().rootTypes.cos, apiVar().cmdObjs.setLabel, val, devId) } @@ -4667,24 +4868,15 @@ def setProtLabel(child, label, virtual=false) { def setStructureAway(child, value, virtual=false) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() def val = value?.toBoolean() - def virt = virtual.toBoolean() - if(virt && atomicState?.vThermostats && devId) { - if(atomicState?."vThermostat${devId}") { - def pdevId = atomicState?."vThermostatMirrorId${devId}" - def pChild - if(pdevId) { pChild = getChildDevice(pdevId) } + def str1 = "setStructureAway | " + def strAction = "" + strAction = "Setting Nest Location:" + def strArgs = " (${child?.device?.displayName} ${!devId ? "" : "- ${devId}"} to (${val ? "Away" : "Home"})" - if(pChild) { - if(val) { - pChild.away() - } else { - pChild.present() - } - } else { LogAction("setStructureAway - CANNOT Set Thermostat${pdevId} Presence: (${val}) child ${pChild}", "warn", true) } - } - } else { - LogAction("setStructureAway - Setting Nest Location: (${child?.device?.displayName})${!devId ? "" : " ${devId}"} to (${val ? "Away" : "Home"})", "debug", true) + def pChild = getPdevId(virtual.toBoolean(), devId) + if(pChild == null) { + LogAction(str1+strAction+strArgs, "debug", true) if(val) { def ret = sendNestApiCmd(atomicState?.structures, apiVar().rootTypes.struct, apiVar().cmdObjs.away, "away", devId) // Below is to ensure automations read updated value even if queued @@ -4706,15 +4898,27 @@ def setStructureAway(child, value, virtual=false) { } return ret } + } else { + if(pChild != "00000") { + LogAction(str1+strAction+strArgs, "debug", true) + if(val) { + pChild.away() + } else { + pChild.present() + } + return + } else { + strAction = "CANNOT Set Location" + } } + LogAction(str1+strAction+strArgs, "warn", true) } def setTstatTempScale(child, tScale, virtual=false) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() def tempScale = tScale.toString() - def virt = virtual.toBoolean() -// INCOMPLETE: This is not used anywhere. A command to set Temp Scale is not available in the dth for a callback +// INCOMPLETE: This is not used anywhere. A command to set Temp Scale is not available in the dth for a callback LogAction("setTstatTempScale: INCOMPLETE Thermostat${!devId ? "" : " ${devId}"} tempScale: (${tempScale})", "debug", true) return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.setTscale, tempScale, devId) @@ -4723,9 +4927,8 @@ def setTstatTempScale(child, tScale, virtual=false) { def setTstatLabel(child, label, virtual=false) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() def val = label - def virt = virtual.toBoolean() -// INCOMPLETE: This is not used anywhere. A command to set label is not available in the dth for a callback +// INCOMPLETE: This is not used anywhere. A command to set label is not available in the dth for a callback LogAction("setTstatLabel: INCOMPLETE Thermostat${!devId ? "" : " ${devId}"} Label: (${val})", "debug", true) return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.setLabel, val, devId) @@ -4734,171 +4937,194 @@ def setTstatLabel(child, label, virtual=false) { def setFanMode(child, fanOn, virtual=false) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() def val = fanOn.toBoolean() - def virt = virtual.toBoolean() - if(virt && atomicState?.vThermostats && devId) { - if(atomicState?."vThermostat${devId}") { - def pdevId = atomicState?."vThermostatMirrorId${devId}" - def pChild - if(pdevId) { pChild = getChildDevice(pdevId) } + def str1 = "setFanMode | " + def strAction = "" + strAction = "Setting" + def strArgs = " ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) Fan Mode to (${val ? "On" : "Auto"})" - if(pChild) { - if(val) { - pChild.fanOn() - } else { - pChild.fanAuto() - } - } else { LogAction("setFanMode - CANNOT Set Thermostat${pdevId} FanMode: (${fanOn}) child ${pChild}", "warn", true) } - } - } else { - LogAction("setFanMode | Setting ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) Fan Mode to (${val ? "On" : "Auto"})", "debug", true) + def pChild = getPdevId(virtual.toBoolean(), devId) + if(pChild == null) { + LogAction(str1+strAction+strArgs, "debug", true) return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.fanActive, val, devId) + } else { + if(pChild != "00000") { + LogAction(str1+strAction+strArgs, "debug", true) + if(val) { + pChild.fanOn() + } else { + pChild.fanAuto() + } + return + } else { + strAction = "CANNOT Set" + } } + LogAction(str1+strAction+strArgs, "warn", true) } def setHvacMode(child, mode, virtual=false) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() - def virt = virtual.toBoolean() - if(virt && atomicState?.vThermostats && devId) { - if(atomicState?."vThermostat${devId}") { - def pdevId = atomicState?."vThermostatMirrorId${devId}" - def pChild - if(pdevId) { pChild = getChildDevice(pdevId) } + def str1 = "setHvacMode | " + def strAction = "" + strAction = "Setting" + def strArgs = " ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) HVAC Mode to (${mode})" - if(pChild) { - switch (mode) { - case "heat-cool": - pChild.auto() - break - case "heat": - pChild.heat() - break - case "cool": - pChild.cool() - break - case "eco": - pChild.eco() - break - case "off": - pChild.off() - break - case "emergency heat": - pChild.emergencyHeat() - break - default: - LogAction("setHvacMode: Invalid Request: ${mode}", "warn", true) - break - } - } else { LogAction("setHvacMode - CANNOT Set Thermostat${pdevId} Mode: (${mode}) child ${pChild}", "warn", true) } - } - } else { - LogAction("setHvacMode | Setting ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) HVAC Mode to (${mode})", "debug", true) + def pChild = getPdevId(virtual.toBoolean(), devId) + if(pChild == null) { + LogAction(str1+strAction+strArgs, "debug", true) return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.hvacMode, mode.toString(), devId) + } else { + if(pChild != "00000") { + LogAction(str1+strAction+strArgs, "debug", true) + switch (mode) { + case "heat-cool": + pChild.auto() + break + case "heat": + pChild.heat() + break + case "cool": + pChild.cool() + break + case "eco": + pChild.eco() + break + case "off": + pChild.off() + break + case "emergency heat": + pChild.emergencyHeat() + break + default: + LogAction("setHvacMode: Invalid Request: ${mode}", "warn", true) + break + } + return + } else { + strAction = "CANNOT Set " + } } + + LogAction(str1+strAction+strArgs, "warn", true) } def setTargetTemp(child, unit, temp, mode, virtual=false) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() - def virt = virtual.toBoolean() - if(virt && atomicState?.vThermostats && devId) { - if(atomicState?."vThermostat${devId}") { - def pdevId = atomicState?."vThermostatMirrorId${devId}" - def pChild - if(pdevId) { pChild = getChildDevice(pdevId) } - def appId = atomicState?."vThermostatChildAppId${devId}" - def automationChildApp - if(appId) { automationChildApp = getChildApps().find{ it.id == appId } } - if(automationChildApp) { - def res = automationChildApp.remSenTempUpdate(temp,mode) - if(res) { return } - } - if(pChild) { - if(mode == 'cool') { - pChild.setCoolingSetpoint(temp) - } else if(mode == 'heat') { - pChild.setHeatingSetpoint(temp) - } else { LogAction("setTargetTemp - UNKNOWN MODE (${mode}) child ${pChild}", "warn", true) } - } else { LogAction("setTargetTemp - CANNOT Set Thermostat${pdevId} Temp: (${temp}${tUnitStr()} | Mode: (${mode}) | child ${pChild}", "warn", true) } - } - } else { - LogAction("setTargetTemp | Setting ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) Target Temp to (${temp}${tUnitStr()})", "debug", true) + def str1 = "setTargetTemp | " + def strAction = "" + strAction = "Setting" + def strArgs = " ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) Target Temp to (${temp}${tUnitStr()})" + + def pChild = getPdevId(virtual.toBoolean(), devId) + if(pChild == null) { + LogAction(str1+strAction+strArgs, "debug", true) if(unit == "C") { return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.targetC, temp, devId) } else { return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.targetF, temp, devId) } + } else { + LogAction(str1+strAction+strArgs, "debug", true) + def appId = atomicState?."vThermostatChildAppId${devId}" + def automationChildApp + if(appId) { automationChildApp = getChildApps().find{ it?.id == appId } } + if(automationChildApp) { + def res = automationChildApp.remSenTempUpdate(temp,mode) + if(res) { return } + } + if(pChild != "00000") { + if(mode == 'cool') { + pChild.setCoolingSetpoint(temp) + } else if(mode == 'heat') { + pChild.setHeatingSetpoint(temp) + } else { LogAction("setTargetTemp - UNKNOWN MODE (${mode}) child ${pChild}", "warn", true) } + return + } else { + strAction = "CANNOT Set" + } } + + LogAction(str1+strAction+strArgs, "warn", true) } def setTargetTempLow(child, unit, temp, virtual=false) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() - def virt = virtual.toBoolean() - - if(virt && atomicState?.vThermostats && devId) { - if(atomicState?."vThermostat${devId}") { - def pdevId = atomicState?."vThermostatMirrorId${devId}" - def pChild - if(pdevId) { pChild = getChildDevice(pdevId) } - def appId = atomicState?."vThermostatChildAppId${devId}" - def automationChildApp - if(appId) { automationChildApp = getChildApps().find{ it.id == appId } } + def str1 = "setTargetTempLow | " + def strAction = "" + strAction = "Setting" + def strArgs = " ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) Target Temp Low to (${temp}${tUnitStr()})" - if(automationChildApp) { - def res = automationChildApp.remSenTempUpdate(temp,"heat") - if(res) { return } - } - - if(pChild) { - pChild.setHeatingSetpoint(temp) - } else { LogAction("setTargetTemp - CANNOT Set Thermostat${pdevId} HEAT: (${temp})${unit} child ${pChild}", "warn", true) } - } - } else { - LogAction("setTargetTempLow | Setting ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) Target Temp Low to (${temp}${tUnitStr()})", "debug", true) + def pChild = getPdevId(virtual.toBoolean(), devId) + if(pChild == null) { + LogAction(str1+strAction+strArgs, "debug", true) if(unit == "C") { return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.targetLowC, temp, devId) } else { return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.targetLowF, temp, devId) } + } else { + LogAction(str1+strAction+strArgs, "debug", true) + def appId = atomicState?."vThermostatChildAppId${devId}" + def automationChildApp + if(appId) { automationChildApp = getChildApps().find{ it?.id == appId } } + + if(automationChildApp) { + def res = automationChildApp.remSenTempUpdate(temp,"heat") + if(res) { return } + } + if(pChild != "00000") { + pChild.setHeatingSetpoint(temp) + return + } else { + strAction = "CANNOT Set" + } } + + LogAction(str1+strAction+strArgs, "warn", true) } def setTargetTempHigh(child, unit, temp, virtual=false) { def devId = !child?.device?.deviceNetworkId ? null : child?.device?.deviceNetworkId.toString() - def virt = virtual.toBoolean() - - if(virt && atomicState?.vThermostats && devId) { - if(atomicState?."vThermostat${devId}") { - def pdevId = atomicState?."vThermostatMirrorId${devId}" - def pChild - if(pdevId) { pChild = getChildDevice(pdevId) } - def appId = atomicState?."vThermostatChildAppId${devId}" - def automationChildApp - if(appId) { automationChildApp = getChildApps().find{ it.id == appId } } + def str1 = "setTargetTempHigh | " + def strAction = "" + strAction = "Setting" + def strArgs = " ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) Target Temp High to (${temp}${tUnitStr()})" - if(automationChildApp) { - def res = automationChildApp.remSenTempUpdate(temp,"cool") - if(res) { return } - } - - if(pChild) { - pChild.setCoolingSetpoint(temp) - } else { LogAction("setTargetTemp - CANNOT Set Thermostat${pdevId} COOL: (${temp})${unit} child ${pChild}", "warn", true) } - } - } else { - LogAction("setTargetTempHigh | Setting ${virtual ? "Virtual " : ""}Thermostat (${child?.device?.displayName} - ${devId}) Target Temp High to (${temp}${tUnitStr()})", "debug", true) + def pChild = getPdevId(virtual.toBoolean(), devId) + if(pChild == null) { + LogAction(str1+strAction+strArgs, "debug", true) if(unit == "C") { return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.targetHighC, temp, devId) } else { return sendNestApiCmd(devId, apiVar().rootTypes.tstat, apiVar().cmdObjs.targetHighF, temp, devId) } + } else { + LogAction(str1+strAction+strArgs, "debug", true) + def appId = atomicState?."vThermostatChildAppId${devId}" + def automationChildApp + if(appId) { automationChildApp = getChildApps().find{ it?.id == appId } } + + if(automationChildApp) { + def res = automationChildApp.remSenTempUpdate(temp,"cool") + if(res) { return } + } + if(pChild != "00000") { + pChild.setCoolingSetpoint(temp) + return + } else { + strAction = "CANNOT Set" + } } + + LogAction(str1+strAction+strArgs, "warn", true) } def sendNestApiCmd(cmdTypeId, cmdType, cmdObj, cmdObjVal, childId) { @@ -4910,7 +5136,7 @@ def sendNestApiCmd(cmdTypeId, cmdType, cmdObj, cmdObjVal, childId) { try { if(cmdTypeId) { - def qnum = getQueueNumber(cmdTypeId, childId) + def qnum = getQueueNumber(cmdTypeId) if(qnum == -1 ) { return false } atomicState?.pollBlocked = true @@ -4938,7 +5164,7 @@ def sendNestApiCmd(cmdTypeId, cmdType, cmdObj, cmdObjVal, childId) { skipped = true tempQueue << newCmd } else if(newCmd[1] == cmdType?.toString() && newCmd[2] == cmdObj?.toString() && - newCmd[2] != apiVar().cmdObjs.away && newCmd[2] != apiVar().cmdObjs.fanActive && newCmd[2] != apiVar().cmdObjs.fanTimer) { + newCmd[2] != apiVar().cmdObjs.away && newCmd[2] != apiVar().cmdObjs.fanActive && newCmd[2] != apiVar().cmdObjs.fanTimer && newCmd[2] != apiVar().cmdObjs.eta) { // if we are changing the same setting again use latest - this is Temp settings, hvac replaced = true tempQueue << cmdData @@ -4961,7 +5187,7 @@ def sendNestApiCmd(cmdTypeId, cmdType, cmdObj, cmdObjVal, childId) { LogAction("${str} Cmd to Queue ${qnum} (qsize: ${tempQueue?.size()}): $cmdTypeId, $cmdType, $cmdObj, $cmdObjVal, $childId", "info", true) atomicState?.lastQcmd = cmdData - schedNextWorkQ(childId) + schedNextWorkQ() return true } else { @@ -4976,7 +5202,13 @@ def sendNestApiCmd(cmdTypeId, cmdType, cmdObj, cmdObjVal, childId) { } } -private getQueueNumber(cmdTypeId, childId) { +/* + * Each nest device has its own queue (as does the nest structure itself) + * Queues are "assigned" dynamically as they are needed + * Each queue has it own "free" command counts, then commands are limited to 1 per minute. + */ + +private getQueueNumber(cmdTypeId) { if(!atomicState?.cmdQlist) { atomicState.cmdQlist = [] } def cmdQueueList = atomicState?.cmdQlist def qnum = cmdQueueList.indexOf(cmdTypeId) @@ -4987,13 +5219,21 @@ private getQueueNumber(cmdTypeId, childId) { qnum = cmdQueueList.indexOf(cmdTypeId) atomicState?."cmdQ${qnum}" = null setLastCmdSentSeconds(qnum, null) - setRecentSendCmd(qnum, null) + //setRecentSendCmd(qnum, null) } qnum = cmdQueueList.indexOf(cmdTypeId) - if(qnum == -1 ) { LogAction("getQueueNumber: NOT FOUND", "warn", true ) } + if(qnum == -1 || qnum == null) { LogAction("getQueueNumber: NOT FOUND", "warn", true ) } + else { + if(getLastCmdSentSeconds(qnum) > 3600) { setRecentSendCmd(qnum, cmdMaxVal()) } // if nothing sent in last hour, reset command limit + } return qnum } +/* + * Queues are processed in the order in which commands were sent (across all queues) + * This maintains proper state ordering for changes, as commands can have dependencies in order + */ + def getQueueToWork() { def qnum def savedtim @@ -5011,40 +5251,59 @@ def getQueueToWork() { } } LogTrace("getQueueToWork queue: ${qnum}") + if(qnum != -1 && qnum != null) { + if(getLastCmdSentSeconds(qnum) > 3600) { setRecentSendCmd(qnum, cmdMaxVal()) } // if nothing sent in last hour, reset command limit + } return qnum } -void schedNextWorkQ(childId, useShort=false) { - def cmdDelay = getChildWaitVal() - - def allowAsync = false - if(atomicState?.appData && atomicState?.appData?.pollMethod?.allowAsync) { - allowAsync = true - } +private cmdMaxVal() { return 2 } - if(useShort && allowAsync) { cmdDelay = 0 } +void schedNextWorkQ(useShort=false) { + def cmdDelay = getChildWaitVal() + if(useShort) { cmdDelay = 0 } // // This is throttling the rate of commands to the Nest service for this access token. // If too many commands are sent Nest throttling could shut all write commands down for 1 hour to the device or structure - // This allows up to 3 commands if none sent in the last hour, then only 1 per 60 seconds. Nest could still + // This allows up to 3 commands if none sent in the last hour, then only 1 per 60 seconds. Nest could still // throttle this if the battery state on device is low. // https://nestdevelopers.io/t/user-receiving-exceeded-rate-limit-on-requests-please-try-again-later/354 // def qnum = getQueueToWork() def timeVal = cmdDelay + def str = "" + def queueItemsAvail + def lastCommandSent if(qnum != null) { - if( !(getRecentSendCmd(qnum) > 0 || getLastCmdSentSeconds(qnum) > 60) ) { - timeVal = (60 - getLastCmdSentSeconds(qnum) + getChildWaitVal()) - } - def str = timeVal > cmdDelay ? "*RATE LIMITING ON* " : "" - LogAction("schedNextWorkQ │ ${str}queue: ${qnum} │ schedTime: ${timeVal} │ recentSendCmd: ${getRecentSendCmd(qnum)} │ last seconds: ${getLastCmdSentSeconds(qnum)} │ cmdDelay: ${cmdDelay} │ allowAsync: ${allowAsync}", "info", true) - } - if(timeVal != 0) { - runIn(timeVal, "workQueue", [overwrite: true]) + queueItemsAvail = getRecentSendCmd(qnum) + lastCommandSent = getLastCmdSentSeconds(qnum) + if( (queueItemsAvailable == 0 && lastCommandSent > 60) ) { queueItemsAvail = 1 } + if( queueItemsAvail <= 0 || atomicState?.apiRateLimited) { + timeVal = 60 + cmdDelay + //atomicState?.workQrunInActive = false + } else if(lastCommandSent < 60) { + timeVal = (60 - lastCommandSent + cmdDelay) + if(queueItemsAvail > 0) { timeVal = 0 } + } + str = timeVal > cmdDelay || atomicState?.apiRateLimited ? "*RATE LIMITING ON* " : "" + //LogAction("schedNextWorkQ │ ${str}queue: ${qnum} │ schedTime: ${timeVal} │ recentSendCmd: ${queueItemsAvail} │ last seconds: ${lastCommandSent} │ cmdDelay: ${cmdDelay} | runInActive: ${atomicState?.workQrunInActive} | Api Limited: ${atomicState?.apiRateLimited}", "info", true) } else { - workQueue() + timeVal = 0 + } + def actStr = "ALREADY PENDING " + if(cmdIsProc()) { actStr = "COMMAND RUNNING " } + if(!atomicState?.workQrunInActive && !cmdIsProc() ) { + atomicState?.workQrunInActive = true + if(timeVal != 0) { + actStr = "RUNIN " + runIn(timeVal, "workQueue", [overwrite: true]) + } else { + actStr = "DIRECT CALL " + workQueue() + } } + LogAction("schedNextWorkQ ${actStr} │ ${str}queue: ${qnum} │ schedTime: ${timeVal} │ recentSendCmd: ${queueItemsAvail} │ last seconds: ${lastCommandSent} │ cmdDelay: ${cmdDelay} | runInActive: ${atomicState?.workQrunInActive} | command proc: ${cmdIsProc()} | Api Limited: ${atomicState?.apiRateLimited}", "info", true) } private getRecentSendCmd(qnum) { @@ -5052,7 +5311,11 @@ private getRecentSendCmd(qnum) { } private setRecentSendCmd(qnum, val) { - atomicState."recentSendCmd${qnum}" = val + if(qnum != null) { + atomicState."recentSendCmd${qnum}" = val + } else { + LogAction("setRecentSendCmd qnum $qnum is null", "error", true) + } return } @@ -5062,11 +5325,12 @@ def sendEcoActionDescToDevice(dev, desc) { } } -private getLastCmdSentSeconds(qnum) { return atomicState?."lastCmdSentDt${qnum}" ? GetTimeDiffSeconds(atomicState?."lastCmdSentDt${qnum}", null, "getLastCmdSentSeconds") : 3601 } +private getLastAnyCmdSentSeconds() { return getTimeSeconds("lastCmdSentDt", 3601, "getLastAnyCmdSentSeconds") } +private getLastCmdSentSeconds(qnum) { return getTimeSeconds("lastCmdSentDt${qnum}", 3601, "getLastCmdSentSeconds") } private setLastCmdSentSeconds(qnum, val) { - atomicState."lastCmdSentDt${qnum}" = val - atomicState.lastCmdSentDt = val + updTimestampMap("lastCmdSentDt${qnum}", val) + if(val != null) { updTimestampMap("lastCmdSentDt", val) } } def storeLastCmdData(cmd, qnum) { @@ -5074,7 +5338,7 @@ def storeLastCmdData(cmd, qnum) { def newVal = ["qnum":qnum, "obj":cmd[2], "value":cmd[3], "date":getDtNow()] def list = atomicState?.cmdDetailHistory ?: [] - def listSize = 30 + def listSize = 20 if(list?.size() < listSize) { list.push(newVal) } @@ -5095,26 +5359,22 @@ def storeLastCmdData(cmd, qnum) { void workQueue() { LogTrace("workQueue") + atomicState?.workQrunInActive = false //def cmdDelay = getChildWaitVal() if(!atomicState?.cmdQlist) { atomicState?.cmdQlist = [] } def cmdQueueList = atomicState?.cmdQlist def qnum = getQueueToWork() if(qnum == null) { qnum = 0 } + if(!atomicState?."cmdQ${qnum}") { atomicState."cmdQ${qnum}" = [] } - def allowAsync = false - def metstr = "sync" - if(atomicState?.appData && atomicState?.appData?.pollMethod?.allowAsync) { - allowAsync = true - metstr = "async" - } + def metstr = "async" - if(!atomicState?."cmdQ${qnum}") { atomicState."cmdQ${qnum}" = [] } def cmdQueue = atomicState?."cmdQ${qnum}" try { if(cmdQueue?.size() > 0) { LogAction("workQueue │ Run Queue: ${qnum} | ($metstr)", "trace", true) - runIn(60, "workQueue", [overwrite: true]) // lost schedule catchall + runIn(90, "workQueue", [overwrite: true]) // lost schedule catchall if(!cmdIsProc()) { cmdProcState(true) atomicState?.pollBlocked = true @@ -5127,7 +5387,7 @@ void workQueue() { atomicState?."cmdQ${qnum}" = cmdQueue def cmdres - if(getLastCmdSentSeconds(qnum) > 3600) { setRecentSendCmd(qnum, 3) } // if nothing sent in last hour, reset 3 command limit + if(getLastCmdSentSeconds(qnum) > 3600) { setRecentSendCmd(qnum, cmdMaxVal()) } // if nothing sent in last hour, reset command limit storeLastCmdData(cmd, qnum) @@ -5137,12 +5397,8 @@ void workQueue() { atomicState.forceChildUpd = true cmdres = true } else { - if(allowAsync) { - cmdres = queueProcNestApiCmd(getNestApiUrl(), cmd[0], cmd[1], cmd[2], cmd[3], qnum, cmd) - return - } else { - cmdres = procNestApiCmd(getNestApiUrl(), cmd[0], cmd[1], cmd[2], cmd[3], qnum) - } + cmdres = queueProcNestApiCmd(getNestApiUrl(), cmd[0], cmd[1], cmd[2], cmd[3], qnum, cmd) + return } finishWorkQ(cmd, cmdres) } else { LogAction("workQueue: busy processing command", "warn", true) } @@ -5157,6 +5413,7 @@ void workQueue() { atomicState.forceChildUpd = true atomicState?.pollBlocked = false atomicState?.pollBlockedReason = null + atomicState?.workQrunInActive = true runIn(60, "workQueue", [overwrite: true]) runIn((60 + 4), "postCmd", [overwrite: true]) return @@ -5164,7 +5421,7 @@ void workQueue() { } def finishWorkQ(cmd, result) { - LogTrace("finishWorkQ cmd: $cmd result: $result") + LogTrace("finishWorkQ cmd: $cmd result: $result") def cmdDelay = getChildWaitVal() if( !result ) { @@ -5180,13 +5437,13 @@ def finishWorkQ(cmd, result) { atomicState.forceChildUpd = true } - atomicState?.cmdLastProcDt = getDtNow() + updTimestampMap("cmdLastProcDt", getDtNow()) cmdProcState(false) def qnum = getQueueToWork() if(qnum == null) { qnum = 0 } + if(!atomicState?."cmdQ${qnum}") { atomicState."cmdQ${qnum}" = [] } - if(!atomicState?."cmdQ${qnum}") { atomicState?."cmdQ${qnum}" = [] } def cmdQueue = atomicState?."cmdQ${qnum}" if(cmdQueue?.size() == 0) { atomicState.pollBlocked = false @@ -5194,7 +5451,7 @@ def finishWorkQ(cmd, result) { atomicState.needChildUpd = true runIn(cmdDelay, "postCmd", [overwrite: true]) } - else { schedNextWorkQ(null, true) } + else { schedNextWorkQ(true) } if(cmdQueue?.size() > 10) { sendMsg("Warning", "There is now ${cmdQueue?.size()} events in the Command Queue. Something must be wrong", true) @@ -5204,7 +5461,8 @@ def finishWorkQ(cmd, result) { } def queueProcNestApiCmd(uri, typeId, type, obj, objVal, qnum, cmd, redir = false) { - LogTrace("queueProcNestApiCmd: typeId: ${typeId}, type: ${type}, obj: ${obj}, objVal: ${objVal}, qnum: ${qnum}, isRedirUri: ${redir}") + def myStr = "queueProcNestApiCmd" + LogTrace("${myStr}: typeId: ${typeId}, type: ${type}, obj: ${obj}, objVal: ${objVal}, qnum: ${qnum}, isRedirUri: ${redir}") def result = false if(!atomicState?.authToken) { return result } @@ -5218,18 +5476,11 @@ def queueProcNestApiCmd(uri, typeId, type, obj, objVal, qnum, cmd, redir = false headers: ["Content-Type": "application/json", "Authorization": "Bearer ${atomicState?.authToken}"], body: data.toString() ] - LogTrace("queueProcNestApiCmd Url: $uri | params: ${params}") + LogTrace("${myStr} Url: $uri | params: ${params}") LogAction("Processing Queued Cmd: [ObjId: ${typeId} | ObjType: ${type} | ObjKey: ${obj} | ObjVal: ${objVal} | QueueNum: ${qnum} | Redirect: ${redir}]", "trace", true) atomicState?.lastCmdSent = "$type: (${obj}: ${objVal})" - if(!redir && (getRecentSendCmd(qnum) > 0) && (getLastCmdSentSeconds(qnum) < 60)) { - def val = getRecentSendCmd(qnum) - val -= 1 - setRecentSendCmd(qnum, val) - } - setLastCmdSentSeconds(qnum, getDtNow()) - - LogTrace("queueProcNestApiCmd time update recentSendCmd: ${getRecentSendCmd(qnum)} last seconds:${getLastCmdSentSeconds(qnum)} queue: ${qnum}") + adjThrottle(qnum, redir, myStr) def asyncargs = [ typeId: typeId, @@ -5242,9 +5493,29 @@ def queueProcNestApiCmd(uri, typeId, type, obj, objVal, qnum, cmd, redir = false asynchttp_v1.put(nestCmdResponse, params, asyncargs) } catch(ex) { - log.error "queueProcNestApiCmd (command: $cmd) Exception:", ex - sendExceptionData(ex, "queueProcNestApiCmd") + log.error "${myStr} (command: $cmd) Exception:", ex + sendExceptionData(ex, myStr) + } +} + +def adjThrottle(qnum, redir, callerStr) { + if(!redir) { + def t0 = getRecentSendCmd(qnum) + def val = t0 + if(t0 > 0 /* && (getLastCmdSentSeconds(qnum) < 60) */ ) { + val -= 1 + } + def t1 = getLastCmdSentSeconds(qnum) + if(t1 > 120 && t1 < 60*45 && val < (cmdMaxVal() - 1) ) { + val += 1 + } + if(t1 > 60*30 && t1 < 60*45 && val < cmdMaxVal() ) { + val += 1 + } + LogTrace("${callerStr} adjThrottle orig recentSendCmd: ${t0} | new: ${val} | last seconds: ${t1} queue: ${qnum}") + setRecentSendCmd(qnum, val) } + setLastCmdSentSeconds(qnum, getDtNow()) } def nestCmdResponse(resp, data) { @@ -5269,34 +5540,56 @@ def nestCmdResponse(resp, data) { if(resp?.status == 200) { LogAction("nestCmdResponse | Processed Queue: ${qnum} | Obj: ($type{$obj:$objVal}) SUCCESSFULLY!", "info", true) apiIssueEvent(false) - incCmdCnt() + incrementCntByKey("apiCommandCnt") atomicState?.lastCmdSentStatus = "ok" - atomicState?.apiRateLimited = false - atomicState?.apiCmdFailData = null + //atomicState?.apiRateLimited = false + //atomicState?.apiCmdFailData = null result = true - } else { - apiIssueEvent(true) + } +/* + if(resp?.status == 429) { + // requeue command + def newCmd = [command[0], command[1], command[2], command[3], command[4]] + def tempQueue = [] + tempQueue << newCmd + if(!atomicState?."cmdQ${qnum}" ) { atomicState."cmdQ${qnum}" = [] } + def cmdQueue = atomicState?."cmdQ${qnum}" + cmdQueue.each { cmd -> + newCmd = [cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]] + tempQueue << newCmd + } + atomicState."cmdQ${qnum}" = tempQueue + } +*/ + if(resp?.status != 200) { atomicState?.lastCmdSentStatus = "failed" if(resp?.hasError()) { apiRespHandler((resp?.getStatus() ?: null), (resp?.getErrorJson() ?: null), "nestCmdResponse", "nestCmdResponse ${qnum} ($type{$obj:$objVal})", true) } + apiIssueEvent(true) + } +/* + if(resp?.status == 429) { + result = true // we requeued the command } +*/ finishWorkQ(command, result) } catch (ex) { - log.error "nestCmdResponse (command: $command) Exception:", ex - sendExceptionData(ex, "nestCmdResponse") - apiIssueEvent(true) atomicState?.lastCmdSentStatus = "failed" + cmdProcState(false) if(resp?.hasError()) { apiRespHandler((resp?.getStatus() ?: null), (resp?.getErrorJson() ?: null), "nestCmdResponse", "nestCmdResponse ${qnum} ($type{$obj:$objVal})", true) } - cmdProcState(false) + apiIssueEvent(true) + log.error "nestCmdResponse (command: $command) Exception:", ex + sendExceptionData(ex, "nestCmdResponse") } } -def procNestApiCmd(uri, typeId, type, obj, objVal, qnum, redir = false) { - LogTrace("procNestApiCmd: typeId: ${typeId}, type: ${type}, obj: ${obj}, objVal: ${objVal}, qnum: ${qnum}, isRedirUri: ${redir}") +def procNestApiCmd(uri, typeId, type, obj, objVal, qnum, origcmd, redir = false) { + def myStr = "procNestApiCmd" + LogTrace("${myStr}: typeId: ${typeId}, type: ${type}, obj: ${obj}, objVal: ${objVal}, qnum: ${qnum}, isRedirUri: ${redir}") def result = false if(!atomicState?.authToken) { return result } @@ -5310,45 +5603,57 @@ def procNestApiCmd(uri, typeId, type, obj, objVal, qnum, redir = false) { query: [ "auth": atomicState?.authToken ], body: data.toString() ] - LogAction("procNestApiCmd Url: $uri | params: ${params}", "trace", true) + LogAction("${myStr} Url: $uri | params: ${params}", "trace", true) atomicState?.lastCmdSent = "$type: (${obj}: ${objVal})" - if(!redir && (getRecentSendCmd(qnum) > 0) && (getLastCmdSentSeconds(qnum) < 60)) { - def val = getRecentSendCmd(qnum) - val -= 1 - setRecentSendCmd(qnum, val) - } - setLastCmdSentSeconds(qnum, getDtNow()) - - LogTrace("procNestApiCmd time update recentSendCmd: ${getRecentSendCmd(qnum)} last seconds:${getLastCmdSentSeconds(qnum)} queue: ${qnum}") + adjThrottle(qnum, redir, myStr) httpPutJson(params) { resp -> def rCode = resp?.status ?: null if(resp?.status == 307) { def newUrl = resp?.headers?.location?.split("\\?") LogTrace("NewUrl: ${newUrl[0]}") - if( procNestApiCmd(newUrl[0], typeId, type, obj, objVal, qnum, true) ) { + if( procNestApiCmd(newUrl[0], typeId, type, obj, objVal, qnum, origcmd, true) ) { result = true } + return result } else if(resp?.status == 200) { - LogAction("procNestApiCmd Processed queue: ${qnum} ($type{$obj:$objVal}) SUCCESSFULLY!", "info", true) + LogAction("${myStr} Processed queue: ${qnum} ($type{$obj:$objVal}) SUCCESSFULLY!", "info", true) apiIssueEvent(false) - incCmdCnt() + incrementCntByKey("apiCommandCnt") atomicState?.lastCmdSentStatus = "ok" - atomicState?.apiRateLimited = false - atomicState?.apiCmdFailData = null + //atomicState?.apiRateLimited = false + //atomicState?.apiCmdFailData = null result = true + return result } - else { - apiIssueEvent(true) - atomicState?.lastCmdSentStatus = "failed" - result = false - apiRespHandler(resp?.status, resp?.data, "procNestApiCmd", "procNestApiCmd ${qnum} ($type{$obj:$objVal})", true) +/* + if(resp?.status == 429) { + // requeue command + def newCmd = [origcmd[0], origcmd[1], origcmd[2], origcmd[3], origcmd[4]] + def tempQueue = [] + tempQueue << newCmd + if(!atomicState?."cmdQ${qnum}" ) { atomicState."cmdQ${qnum}" = [] } + def cmdQueue = atomicState?."cmdQ${qnum}" + cmdQueue.each { cmd -> + newCmd = [cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]] + tempQueue << newCmd + } + atomicState."cmdQ${qnum}" = tempQueue + } +*/ + atomicState?.lastCmdSentStatus = "failed" + result = false + apiRespHandler(resp?.status, resp?.data, myStr, "${myStr} ${qnum} ($type{$obj:$objVal})", true) + apiIssueEvent(true) +/* + if(resp?.status == 429) { + result = true // we requeued the command } +*/ } } catch (ex) { - apiIssueEvent(true) atomicState?.lastCmdSentStatus = "failed" cmdProcState(false) if (ex instanceof groovyx.net.http.HttpResponseException && ex?.response) { @@ -5356,6 +5661,7 @@ def procNestApiCmd(uri, typeId, type, obj, objVal, qnum, redir = false) { } else { sendExceptionData(ex, "procNestApiCmd") } + apiIssueEvent(true) log.error "procNestApiCmd Exception: ($type | $obj:$objVal)", ex } return result @@ -5372,31 +5678,31 @@ def apiRespHandler(code, errJson, methodName, tstr=null, isCmd=false) { result = !errMsg ? "A Bad Request was made to the API..." : errMsg break case 401: - result = !errMsg ? "Authentication ERROR, Please try refreshing your login under Authentication settings..." : errMsg + result = !errMsg ? "Authentication ERROR, Please try refreshing your login under Authentication settings..." : errMsg revokeNestToken() break case 403: - result = !errMsg ? "Forbidden: Your Login Credentials are Invalid..." : errMsg + result = !errMsg ? "Forbidden: Your Login Credentials are Invalid..." : errMsg revokeNestToken() break case 429: - result = !errMsg ? "Requests are currently being blocked because of API Rate Limiting..." : errMsg + result = !errMsg ? "Requests are currently being blocked because of API Rate Limiting..." : errMsg atomicState?.apiRateLimited = true break case 500: - result = !errMsg ? "Internal Nest Error:" : errMsg + result = !errMsg ? "Internal Nest Error:" : errMsg notif = false break case 503: - result = !errMsg ? "There is currently a Nest Service Issue..." : errMsg + result = !errMsg ? "There is currently a Nest Service Issue..." : errMsg notif = false break default: - result = !errMsg ? "Received Response..." : errMsg + result = !errMsg ? "Received Response..." : errMsg notif = false break } - def failData = ["code":code, "msg":result, "method":methodName, "dt":getDtNow()] + def failData = ["code":code, "msg":result, "method":methodName, "dt":getDtNow(), isCmd: isCmd] atomicState?.apiCmdFailData = failData if(notif || isCmd) { failedCmdNotify(failData, tstr) @@ -5405,64 +5711,47 @@ def apiRespHandler(code, errJson, methodName, tstr=null, isCmd=false) { } } -def incApiStrReqCnt() { - long reqCnt = atomicState?.apiStrReqCnt ?: 0 - reqCnt = reqCnt?.toLong()+1 - LogTrace("ApiStrReqCnt: $reqCnt") - atomicState?.apiStrReqCnt = reqCnt?.toLong() -} - -def incApiDevReqCnt() { - long reqCnt = atomicState?.apiDevReqCnt ?: 0 - reqCnt = reqCnt?.toLong()+1 - LogTrace("ApiDevReqCnt: $reqCnt") - atomicState?.apiDevReqCnt = reqCnt?.toLong() -} - -def incApiMetaReqCnt() { - long reqCnt = atomicState?.apiMetaReqCnt ?: 0 - reqCnt = reqCnt?.toLong()+1 - LogTrace("ApiMetaReqCnt: $reqCnt") - atomicState?.apiMetaReqCnt = reqCnt?.toLong() -} - -def incCmdCnt() { - long cmdCnt = atomicState?.apiCommandCnt ?: 0 - cmdCnt = cmdCnt?.toLong()+1 - LogTrace("Api CmdCnt: $cmdCnt") - atomicState?.apiCommandCnt = cmdCnt?.toLong() -} - -def incRestStrEvtCnt() { - long evtCnt = atomicState?.apiRestStrEvtCnt ?: 0 - evtCnt = evtCnt?.toLong()+1 - LogTrace("ApiRestStrEvtCnt: $evtCnt") - atomicState?.apiRestStrEvtCnt = evtCnt?.toLong() -} - -def incAppNotifSentCnt() { - long notCnt = atomicState?.appNotifSentCnt ?: 0 - notCnt = notCnt?.toLong()+1 - LogTrace("AppNotifSentCnt: $notCnt") - atomicState?.appNotifSentCnt = notCnt?.toLong() +private incrementCntByKey(String key) { + long evtCnt = atomicState?."${key}" ?: 0 + // evtCnt = evtCnt?.toLong()+1 + evtCnt++ + LogTrace("${key?.toString()?.capitalize()}: $evtCnt") + atomicState?."${key}" = evtCnt?.toLong() } /************************************************************************************************ | Push Notification Functions | *************************************************************************************************/ -def pushStatus() { return (settings?.recipients || settings?.phone || settings?.usePush) ? (settings?.usePush ? "Push Enabled" : "Enabled") : null } +def pushStatus() { return (settings?.phone || settings?.usePush || settings?.pushoverEnabled) ? ((settings?.usePush || (settings?.pushoverEnabled && settings?.pushoverDevices)) ? "Push Enabled" : "Enabled") : null } //def getLastMsgSec() { return !atomicState?.lastMsgDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastMsgDt, null, "getLastMsgSec").toInteger() } -def getLastUpdMsgSec() { return !atomicState?.lastUpdMsgDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastUpdMsgDt, null, "getLastUpdMsgSec").toInteger() } -def getLastMissPollMsgSec() { return !atomicState?.lastMisPollMsgDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastMisPollMsgDt, null, "getLastMissPollMsgSec").toInteger() } -def getLastApiIssueMsgSec() { return !atomicState?.lastApiIssueMsgDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastApiIssueMsgDt, null, "getLastApiIssueMsgSec").toInteger() } -def getLastLogRemindMsgSec() { return !atomicState?.lastLogRemindMsgDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastLogRemindMsgDt, null, "getLastLogRemindMsgSec").toInteger() } -def getLastFailedCmdMsgSec() { return !atomicState?.lastFailedCmdMsgDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastFailedCmdMsgDt, null, "getLastFailedCmdMsgSec").toInteger() } -def getLastDevHealthMsgSec() { return !atomicState?.lastDevHealthMsgData?.dt ? 100000 : GetTimeDiffSeconds(atomicState?.lastDevHealthMsgData?.dt, null, "getLastDevHealthMsgSec").toInteger() } -def getDebugLogsOnSec() { return !atomicState?.debugEnableDt ? 0 : GetTimeDiffSeconds(atomicState?.debugEnableDt, null, "getDebugLogsOnSec").toInteger() } -def getRecipientsSize() { return !settings.recipients ? 0 : settings?.recipients?.size() } +def getLastUpdMsgSec() { return getTimeSeconds("lastUpdMsgDt", 100000, "getLastUpdMsgSec").toInteger() } +def getLastMissPollMsgSec() { return getTimeSeconds("lastMisPollMsgDt", 100000, "getLastMissPollMsgSec").toInteger() } +def getLastApiIssueMsgSec() { return getTimeSeconds("lastApiIssueMsgDt", 100000, "getLastApiIssueMsgSec").toInteger() } +def getLastLogRemindMsgSec() { return getTimeSeconds("lastLogRemindMsgDt", 100000, "getLastLogRemindMsgSec").toInteger() } +def getLastFailedCmdMsgSec() { return getTimeSeconds("lastFailedCmdMsgDt", 100000, "getLastFailedCmdMsgSec").toInteger() } +def getDebugLogsOnSec() { return getTimeSeconds("debugEnableDt", 0, "getDebugLogsOnSec").toInteger() } + +//PushOver-Manager Input Generation Functions +private getPushoverSounds(){return (Map) atomicState?.pushoverManager?.sounds?:[:]} +private getPushoverDevices(){List opts=[];Map pmd=atomicState?.pushoverManager?:[:];pmd?.apps?.each{k,v->if(v&&v?.devices&&v?.appId){Map dm=[:];v?.devices?.sort{}?.each{i->dm["${i}_${v?.appId}"]=i};addInputGrp(opts,v?.appName,dm);}};return opts;} +private inputOptGrp(List groups,String title){def group=[values:[],order:groups?.size()];group?.title=title?:"";groups<r[v]=v;return r;}} +private addInputGrp(List groups,String title,values){if(values instanceof List){values=listToMap(values)};values.inject(inputOptGrp(groups,title)){r,k,v->return addInputValues(r,k,v)};return groups;} +private addInputGrp(values){addInputGrp([],null,values)} +//PushOver-Manager Location Event Subscription Events, Polling, and Handlers +public pushover_init(){subscribe(location,"pushoverManager",pushover_handler);pushover_poll()} +public pushover_cleanup(){state?.remove("pushoverManager");unsubscribe("pushoverManager");} +public pushover_poll(){sendLocationEvent(name:"pushoverManagerCmd",value:"poll",data:[empty:true],isStateChange:true,descriptionText:"Sending Poll Event to Pushover-Manager")} +public pushover_msg(List devs,Map data){if(devs&&data){sendLocationEvent(name:"pushoverManagerMsg",value:"sendMsg",data:data,isStateChange:true,descriptionText:"Sending Message to Pushover Devices: ${devs}");}} +public pushover_handler(evt){Map pmd=atomicState?.pushoverManager?:[:];switch(evt?.value){case"refresh":def ed = evt?.jsonData;String id = ed?.appId;Map pA = pmd?.apps?.size() ? pmd?.apps : [:];if(id){pA[id]=pA?."${id}"instanceof Map?pA[id]:[:];pA[id]?.devices=ed?.devices?:[];pA[id]?.appName=ed?.appName;pA[id]?.appId=id;pmd?.apps = pA;};pmd?.sounds=ed?.sounds;break;case "reset":pmd=[:];break;};atomicState?.pushoverManager=pmd;} +//Builds Map Message object to send to Pushover Manager +private buildPushMessage(List devices,Map msgData,timeStamp=false){if(!devices||!msgData){return};Map data=[:];data?.appId=app?.getId();data.devices=devices;data?.msgData=msgData;if(timeStamp){data?.msgData?.timeStamp=new Date().getTime()};pushover_msg(devices,data);} def notificationCheck() { + LogTrace("notificationCheck") + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } def nPrefs = atomicState?.notificationPrefs if(!getOk2Notify()) { return } apiIssueNotify(nPrefs?.app?.api?.issueMsg, nPrefs?.app?.api?.rateLimitMsg, nPrefs?.app?.api?.issueMsgWait) @@ -5472,28 +5761,65 @@ def notificationCheck() { } def cameraStreamNotify(child, Boolean streaming) { + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } if(streaming == null || atomicState?.notificationPrefs?.dev?.camera?.streamMsg != true) { return } sendMsg("${child?.device?.displayName} Info", "Streaming is now '${streaming ? "ON" : "OFF"}'", false) } +def getLastDevHealthMsgSec(timeVal) { return !timeVal ? 100000 : GetTimeDiffSeconds(timeVal, null, "getLastDevHealthMsgSec").toInteger() } + def deviceHealthNotify(child, Boolean isHealthy) { // log.trace "deviceHealthNotify(${child?.device?.displayName}, $isHealthy)" + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } def nPrefs = atomicState?.notificationPrefs?.dev?.devHealth + if(isHealthy == true || nPrefs?.healthMsg != true) { + return + } def devLbl = child?.device?.displayName - def sameAsLastDev = (atomicState?.lastDevHealthMsgData?.device == devLbl) - if(isHealthy == true || nPrefs?.healthMsg != true || (getLastDevHealthMsgSec() <= nPrefs?.healthMsgWait.toInteger() && sameAsLastDev) ) { return } - sendMsg("$devLbl Health Warning", "\nDevice is currently OFFLINE. Please check your logs for possible issues.") - atomicState?.lastDevHealthMsgData = ["device":"$devLbl", "dt":getDtNow()] + def devId = !child?.device?.deviceNetworkId ? child?.toString() : child?.device?.deviceNetworkId.toString() + def t0 = atomicState?.lastDevHealthMsgMap ?: [:] + def lastTime = t0 && devId && t0?."${devId}" ? t0["${devId}"].dt : null + if(!devId || getLastDevHealthMsgSec(lastTime) <= nPrefs?.healthMsgWait?.toInteger() ) { + return + } + sendMsg("$devLbl Health Warning", "\nDevice is OFFLINE. Please check your logs for possible issues.") + t0["${devId}"] = ["device":"$devLbl", "dt":getDtNow()] + atomicState.lastDevHealthMsgMap = t0 +} + +def getNestZipCode() { + def tt = getStrucVal("postal_code") + return tt ?: "" +} + +def getNestTimeZone() { + return getStrucVal("time_zone") +} + +def getEtaBegin() { + return getStrucVal("eta_begin") +} + +def getStrucVal(svariable) { + def sData = atomicState?.structData + def sKey = atomicState?.structures + def asStruc = sData && sKey && sData[sKey] ? sData[sKey] : null + def retVal = asStruc ? asStruc[svariable] ?: null : null + return (retVal != null) ? retVal as String : null +} + +def getSecurityState() { + return getStrucVal("wwn_security_state") } def getLocationPresence() { - def away = atomicState?.structData && atomicState?.structures && atomicState?.structData[atomicState?.structures] && atomicState?.structData[atomicState?.structures]?.away ? atomicState?.structData[atomicState?.structures]?.away : null - return (away != null) ? away as String : null + return getStrucVal("away") } def locationPresNotify(pres) { log.trace "locationPresNotify($pres)" if(pres == null) { return } + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } if(atomicState?.notificationPrefs?.locationChg == true) { def lastStatus = atomicState?.curNestLocStatus if(lastStatus != null && lastStatus?.toString() != pres?.toString()) { @@ -5503,62 +5829,80 @@ def locationPresNotify(pres) { atomicState?.curNestLocStatus = pres } +def getApiIssueSec() { return getTimeSeconds("apiIssueDt", 100000, "getApiIssueSec").toInteger() } + def apiIssueNotify(msgOn, rateOn, wait) { + if( (getApiIssueSec() > 600) && (getLastAnyCmdSentSeconds() > 600)) { + updTimestampMap("apiIssueDt", null) + atomicState.apiIssuesList = [] + if(atomicState?.apiRateLimited) { + atomicState.apiRateLimited = false + LogAction("Clearing rate Limit", "info", true) + } + } if(!msgOn || !wait || !(getLastApiIssueMsgSec() > wait.toInteger())) { return } def apiIssue = apiIssues() ? true : false def rateLimit = (rateOn && atomicState?.apiRateLimited) ? true : false - if((apiIssue && !atomicState?.apiIssueDt) || rateLimit) { + if(apiIssue || rateLimit) { def msg = "" - msg += !rateLimit && apiIssue ? "\nThe Nest API appears to be having issues. This will effect the updating of device and location data.\nThe issues started at (${atomicState?.apiIssueDt})" : "" + msg += apiIssue ? "\nThe Nest API appears to be having issues. This will effect the updating of device and location data.\nThe issues started at (${getTimestampVal("apiIssueDt")})" : "" msg += rateLimit ? "${apiIssue ? "\n\n" : "\n"}Your API connection is currently being Rate-limited for excessive commands." : "" - if(sendMsg("${app?.name} API Issue Warning", msg, true)) { - atomicState?.lastApiIssueMsgDt = getDtNow() + if(sendMsg("${app?.label} API Issue Warning", msg, true)) { + updTimestampMap("lastApiIssueMsgDt", getDtNow()) } } } def failedCmdNotify(failData, tstr) { if(!(getLastFailedCmdMsgSec() > 300)) { return } + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } def nPrefs = atomicState?.notificationPrefs def cmdFail = (nPrefs?.app?.api?.cmdFailMsg && failData?.msg != null) ? true : false + def cmdstr = tstr ?: atomicState?.lastCmdSent + def msg = "\nThe (${cmdstr}) CMD sent to the API has failed.\nStatus Code: ${failData?.code}\nErrorMsg: ${failData?.msg}\nDT: ${failData?.dt}" if(cmdFail) { - def cmdstr = tstr ?: atomicState?.lastCmdSent - def msg = "\nThe (${cmdstr}) CMD sent to the API has failed.\nStatus Code: ${failData?.code}\nErrorMsg: ${failData?.msg}\nDT: ${failData?.dt}" - if(sendMsg("${app?.name} API CMD Failed", msg)) { - atomicState?.lastFailedCmdMsgDt = getDtNow() + if(sendMsg("${app?.label} API CMD Failed", msg)) { + updTimestampMap("lastFailedCmdMsgDt", getDtNow()) } } LogAction(msg, (cmdFail ? "error" : "warn"), true) } def loggingRemindNotify(msgOn) { - if( !(settings?.appDebug || settings?.childDebug) || !msgOn || !(getLastLogRemindMsgSec() > 86400)) { return } - if(atomicState?.debugEnableDt == null) { atomicState?.debugEnableDt = getDtNow() } + if( !(settings?.appDebug || settings?.childDebug) || !msgOn || !(getLastLogRemindMsgSec() > 86400)) { return } + if(getTimestampVal("debugEnableDt") == null) { updTimestampMap("debugEnableDt", getDtNow()) } def dbgAlert = (getDebugLogsOnSec() > 86400) if(dbgAlert) { def msg = "Your debug logging has remained enabled for more than 24 hours please disable them to reduce resource usage on ST platform." - if(sendMsg(("${app?.name} Debug Logging Reminder"), msg, true)) { - atomicState?.lastLogRemindMsgDt = getDtNow() + if(sendMsg(("${app?.label} Debug Logging Reminder"), msg, true)) { + updTimestampMap("lastLogRemindMsgDt", getDtNow()) } } } def missPollNotify(on) { def theWait = settings?.misPollNotifyWaitVal ?: 1800 - if(getLastDevicePollSec() < theWait.toInteger()) { - if(!atomicState?.lastDevDataUpd) { + if(getLastDevPollSec() < theWait.toInteger()) { + if(!getTimestampVal("lastDevDataUpd")) { def now = new Date() def val = new Date(now.time - ( (theWait.toInteger()+1) * 60 * 1000) ) // if uninitialized, set 31 mins in past - atomicState?.lastDevDataUpd = formatDt(val) + updTimestampMap("lastDevDataUpd", formatDt(val)) } return } else { - def msg = "\nThe app has not refreshed data in the last (${getLastDevicePollSec()}) seconds.\nPlease try refreshing data using device refresh button." + def msg = "\nThe app has not refreshed data in the last (${getLastDevPollSec()}) seconds.\nPlease try refreshing data using device refresh button." LogAction(msg, "error", true) - def msgWait = atomicState?.notificationPrefs?.msgDefaultWait ?: 900 +/* poll handles this + if(settings?.restStreaming && atomicState?.restStreamingOn) { + restStreamHandler(true) // close the stream if we have not heard from it in a while + //atomicState?.restStreamingOn = false + } +*/ + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } + def msgWait = atomicState?.notificationPrefs?.msgDefaultWait ?: 3600 if(on && getLastMissPollMsgSec() > msgWait.toInteger()) { - if(sendMsg("${app.name} Nest Data update Issue", msg)) { - atomicState?.lastMisPollMsgDt = getDtNow() + if(sendMsg("${app.label} Nest Data update Issue", msg)) { + updTimestampMap("lastMisPollMsgDt", getDtNow()) } } } @@ -5575,10 +5919,11 @@ def minVersionsOk() { return true } -def appUpdateNotify(badAuto=false) { +def appUpdateNotify(badFile=false, badType=null) { + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } def on = atomicState?.notificationPrefs?.app?.updates?.updMsg def wait = atomicState?.notificationPrefs?.app?.updates?.updMsgWait - if(!badAuto && (!on || !wait || !minVersionsOk())) { return } + if(!badFile && (!on || !wait || !minVersionsOk())) { return } if(getLastUpdMsgSec() > wait.toInteger()) { def appUpd = isAppUpdateAvail() == true ? true : false def autoappUpd = isAutoAppUpdateAvail() == true ? true : false @@ -5588,24 +5933,26 @@ def appUpdateNotify(badAuto=false) { def weatherUpd = atomicState?.weatherDevice ? isWeatherUpdateAvail() : false def camUpd = atomicState?.cameras ? isCamUpdateAvail() : false def streamUpd = atomicState?.restStreamingOn ? isStreamUpdateAvail() : false - def blackListed = (atomicState?.appData && !appDevType() && atomicState?.clientBlacklisted) ? true : false - //log.debug "appUpd: $appUpd || protUpd: $protUpd || presUpd: $presUpd || tstatUpd: $tstatUpd || weatherUpd: $weatherUpd || camUpd: $camUpd || blackListed: $blackListed || badAuto: $badAuto" - if(appUpd || autoappUpd || protUpd || presUpd || tstatUpd || weatherUpd || camUpd || streamUpd || blackListed || badAuto) { + def blackListed = (atomicState?.appData && !appDevType() && atomicState?.cltBlacklisted) ? true : false + //log.debug "appUpd: $appUpd || protUpd: $protUpd || presUpd: $presUpd || tstatUpd: $tstatUpd || weatherUpd: $weatherUpd || camUpd: $camUpd || blackListed: $blackListed || badFile: $badFile" + if(appUpd || autoappUpd || protUpd || presUpd || tstatUpd || weatherUpd || camUpd || streamUpd || blackListed || badFile) { def str = "" str += !blackListed ? "" : "\nBlack Listed, please ensure software is up to date then contact developer" - str += !badAuto ? "" : "\nInvalid or Missing Automation File, please Reinstall the correct automation file" + if(badFile && badType) { + str += !badType ? "" : "\nInvalid or Missing ${badType} Code, please Reinstall the correct ${badType} SmartApp Code" + } str += !appUpd ? "" : "\nManager App: v${atomicState?.appData?.updater?.versions?.app?.ver?.toString()}${betaMarker() ? " Beta" : ""}" - str += (!autoappUpd && !badAuto) ? "" : "\nAutomation App: v${atomicState?.appData?.updater?.versions?.autoapp?.ver?.toString()}${betaMarker() ? " Beta" : ""}" + str += (!autoappUpd && !badFile) ? "" : "\nAutomation App: v${atomicState?.appData?.updater?.versions?.autoapp?.ver?.toString()}${betaMarker() ? " Beta" : ""}" str += !protUpd ? "" : "\nProtect: v${atomicState?.appData?.updater?.versions?.protect?.ver?.toString()}" str += !camUpd ? "" : "\nCamera: v${atomicState?.appData?.updater?.versions?.camera?.ver?.toString()}" str += !presUpd ? "" : "\nPresence: v${atomicState?.appData?.updater?.versions?.presence?.ver?.toString()}" str += !tstatUpd ? "" : "\nThermostat: v${atomicState?.appData?.updater?.versions?.thermostat?.ver?.toString()}" // str += !vtstatUpd ? "" : "\nVirtual Thermostat: v${atomicState?.appData?.updater?.versions?.thermostat?.ver?.toString()}" str += !weatherUpd ? "" : "\nWeather App: v${atomicState?.appData?.updater?.versions?.weather?.ver?.toString()}" - str += !streamUpd ? "" : "\nStream Service: v${atomicState?.appData?.eventStreaming?.minVersion?.toString()}" - def t0 = badAuto ? "Warn" : "Info" + str += !streamUpd ? "" : "\nStream Service: v${atomicState?.appData?.updater?.versions?.stream?.ver?.toString()}" + def t0 = badFile ? "Warn" : "Info" if(sendMsg(t0, "${appName()} Update(s) are Available:${str} \n\nPlease visit the IDE to Update code", true)) { - atomicState?.lastUpdMsgDt = getDtNow() + updTimestampMap("lastUpdMsgDt", getDtNow()) } } } @@ -5614,15 +5961,17 @@ def appUpdateNotify(badAuto=false) { def updateHandler() { LogTrace("updateHandler") if(atomicState?.isInstalled) { - if(atomicState?.appData?.updater?.updateType.toString() == "critical" && atomicState?.lastCritUpdateInfo?.ver.toInteger() != atomicState?.appData?.updater?.updateVer.toInteger()) { + if(atomicState?.appData?.updater?.updateType.toString() == "critical" && atomicState?.lastCritUpdateInfo?.ver?.toInteger() != atomicState?.appData?.updater?.updateVer?.toInteger()) { sendMsg("Critical", "There are Critical Updates available for ${appName()}! Please visit the IDE and make sure to update the App and Devices Code") atomicState?.lastCritUpdateInfo = ["dt":getDtNow(), "ver":atomicState?.appData?.updater?.updateVer?.toInteger()] } - if(atomicState?.appData?.updater?.updateMsg != null && atomicState?.appData?.updater?.updateMsg != atomicState?.lastUpdateMsg) { + def t0 = atomicState?.appData?.updater?.updateMsg + // LogAction("updateHandler: t0 is ${t0}", "info", true) + if(t0 != null && t0 != "" && t0 != atomicState?.lastUpdateMsg) { if(getLastUpdateMsgSec() > 86400) { - if(sendMsg("Info", "${atomicState?.updater?.updateMsg}")) { - atomicState.lastUpdateMsgDt = getDtNow() - atomicState.lastUpdateMsg = atomicState?.appData?.updater?.updateMsg + if(sendMsg("Info", "${t0}")) { + updTimestampMap("lastUpdateMsgDt", getDtNow()) + atomicState.lastUpdateMsg = t0 } } } @@ -5631,7 +5980,8 @@ def updateHandler() { def getOk2Notify() { return (daysOk(settings?.quietDays) && notificationTimeOk() && modesOk(settings?.quietModes)) } -def sendMsg(msgType, msg, showEvt=true, people = null, sms = null, push = null, brdcast = null) { +def sendMsg(String msgType, String msg, Boolean showEvt=true, Map pushoverMap=null, sms=null, push=null, brdcast=null) { + //LogAction("sendMsg: msgType: ${msgType}, msg: ${msg}, showEvt: ${showEvt}", "warn", true) LogTrace("sendMsg") def sentstr = "Push" def sent = false @@ -5639,41 +5989,48 @@ def sendMsg(msgType, msg, showEvt=true, people = null, sms = null, push = null, def newMsg = "${msgType}: ${msg}" as String def flatMsg = newMsg.toString().replaceAll("\n", " ") if(!getOk2Notify()) { - LogAction("sendMsg: Skipping Due to Quiet Time ($flatMsg)", "info", true) + LogAction("sendMsg: Message Skipped During Quiet Time ($flatMsg)", "info", true) + if(showEvt) { sendNotificationEvent(newMsg) } } else { if(!brdcast) { - def who = people ? people : settings?.recipients - if(location.contactBookEnabled) { - if(who) { - sentstr = "Pushing to Contacts $who" - sendNotificationToContacts(newMsg, who, [event: showEvt]) - sent = true - } - } else { - LogAction("ContactBook is NOT Enabled on your SmartThings Account", "warn", false) - if(push || settings?.usePush) { - sentstr = "Push Message" + if(push || settings?.usePush) { + sentstr = "Push Message" + if(showEvt) { sendPush(newMsg) // sends push and notification feed - sent = true + } else { + sendPushMessage(newMsg) // sends push } - def thephone = sms ? sms.toString() : settings?.phone ? settings?.phone?.toString() : "" - if(thephone) { - sentstr = "Text Message to Phone $thephone" - def t0 = newMsg.take(140) + sent = true + } + if(settings?.pushoverEnabled && settings?.pushoverDevices) { + sentstr = "Pushover Message" + Map msgObj = [:] + msgObj = pushoverMap ?: [title: msgType, message: msg, priority: (settings?.pushoverPriority?:0)] + if(settings?.pushoverSound) { msgObj?.sound = settings?.pushoverSound } + buildPushMessage(settings?.pushoverDevices, msgObj, true) + sent = true + } + def thephone = sms ? sms.toString() : settings?.phone ? settings?.phone?.toString() : "" + if(thephone) { + sentstr = "Text Message to Phone [${thephone}]" + def t0 = newMsg.take(140) + if(showEvt) { sendSms(thephone as String, t0 as String) // send SMS and notification feed - sent = true + } else { + sendSmsMessage(thephone as String, t0 as String) // send SMS } + sent = true } } else { - sentstr = "Broadcast" - sendPush(newMsg) // sends push and notification feed was sendPushMessage(newMsg) // push but no notification feed + sentstr = "Broadcast Message" + sendPush(newMsg) // sends push and notification feed was sendPushMessage(newMsg) // push but no notification feed sent = true } if(sent) { //atomicState?.lastMsg = flatMsg //atomicState?.lastMsgDt = getDtNow() - LogAction("sendMsg: Sent ${sentstr} Message Sent: ${flatMsg}", "debug", true) - incAppNotifSentCnt() + LogAction("sendMsg: Sent ${sentstr} (${flatMsg})", "debug", true) + incrementCntByKey("appNotifSentCnt") } } } catch (ex) { @@ -5683,28 +6040,19 @@ def sendMsg(msgType, msg, showEvt=true, people = null, sms = null, push = null, return sent } -def getLastWebUpdSec() { return !atomicState?.lastWebUpdDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastWebUpdDt, null, "getLastWebUpdSec").toInteger() } -def getLastWeatherUpdSec() { return !atomicState?.lastWeatherUpdDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastWeatherUpdDt, null, "getLastWeatherUpdSec").toInteger() } -def getLastForecastUpdSec() { return !atomicState?.lastForecastUpdDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastForecastUpdDt, null, "getLastForecastUpdSec").toInteger() } -def getLastAnalyticUpdSec() { return !atomicState?.lastAnalyticUpdDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastAnalyticUpdDt, null, "getLastAnalyticUpdSec").toInteger() } -def getLastUpdateMsgSec() { return !atomicState?.lastUpdateMsgDt ? 100000 : GetTimeDiffSeconds(atomicState?.lastUpdateMsgDt, null, "getLastUpdateMsgSec").toInteger() } +def getLastWebUpdSec() { return getTimeSeconds("lastWebUpdDt", 100000, "getLastWebUpdSec").toInteger() } +def getLastWeatherUpdSec() { return getTimeSeconds("lastWeatherUpdDt", 100000, "getLastWeatherUpdSec").toInteger() } +def getLastForecastUpdSec() { return getTimeSeconds("lastForecastUpdDt", 100000, "getLastForecastUpdSec").toInteger() } +def getLastAnalyticUpdSec() { return getTimeSeconds("lastAnalyticUpdDt", 100000, "getLastAnalyticUpdSec").toInteger() } +def getLastUpdateMsgSec() { return getTimeSeconds("lastUpdateMsgDt", 100000, "getLastUpdateMsgSec").toInteger() } def getStZipCode() { return location?.zipCode?.toString() } -def getNestZipCode() { - if(atomicState?.structures && atomicState?.structData) { - return atomicState?.structData[atomicState?.structures]?.postal_code ? atomicState?.structData[atomicState?.structures]?.postal_code.toString() : "" - } else { return "" } -} -def getNestTimeZone() { - if(atomicState?.structures && atomicState?.structData) { - return atomicState?.structData[atomicState?.structures]?.time_zone ?: null - } else { return null } -} -def updateWebStuff(now = false) { - LogTrace("updateWebStuff") +def updateWebStuff(now=false) { + //LogTrace("updateWebStuff $now") def nnow = now if(!atomicState?.appData) { nnow = true } + LogTrace("updateWebStuff $now $nnow") if(nnow || (getLastWebUpdSec() > (3600*4))) { if(nnow) { getWebFileData() @@ -5715,62 +6063,109 @@ def updateWebStuff(now = false) { if(now) { getWeatherConditions(now) } else { - if(canSchedule()) { runIn(20, "getWeatherConditions", [overwrite: true]) } + runIn(20, "getWeatherConditions", [overwrite: true]) } } if(atomicState?.isInstalled) { - if(getLastAnalyticUpdSec() > (3600*24) && canSchedule()) { runIn(105, "sendInstallData", [overwrite: true]) } + if(getLastAnalyticUpdSec() > (3600*24)) { runIn(105, "sendInstallData", [overwrite: true]) } } if(atomicState?.feedbackPending) { sendFeedbackData() } } def getWeatherConditions(force = false) { - LogTrace("getWeatherConditions") + LogTrace("getWeatherConditions $force") if(atomicState?.weatherDevice) { + def storageApp = getStorageApp() try { LogAction("Retrieving Local Weather Conditions", "info", false) def loc = "" def curWeather = "" def curForecast = "" - def curAstronomy = "" + def curLocation = "" def curAlerts = "" + def curAlertdetail = "" def err = false - def custLoc = getCustWeatherLoc() + def chgd = false + def custLoc = getCustWeatherLoc().toString() + if(custLoc) { - loc = custLoc - curWeather = getWeatherFeature("conditions", loc) - curAlerts = getWeatherFeature("alerts", loc) + loc = custLoc.toString() + curWeather = getTwcConditions(/*loc*/) //getWeatherFeature("conditions", loc) // getTwcConditions(loc) + curLocation = getTwcLocation(/*loc*/) } else { - curWeather = getWeatherFeature("conditions") - curAlerts = getWeatherFeature("alerts") - } - if(getLastForecastUpdSec() > (1800)) { + curWeather = getTwcConditions() //getWeatherFeature("conditions") //getTwcConditions() + curLocation = getTwcLocation() + } + String myLoc = curLocation?.location?.latitude.toString() + "," + curLocation?.location?.longitude.toString() + curAlerts = getTwcAlerts(myLoc) // does not support loc //getWeatherFeature("alerts", loc) // getTwcAlerts(loc) + // atomicState?.curWeather = curWeather + // atomicState?.curLocation = curLocation + // atomicState?.curAlerts = curAlerts + if( getLastForecastUpdSec() > (1800) || + (storageApp && (!getStorageVal("curForecast") /* || !getStorageVal("curAstronomy") */ )) || + (!storageApp && (!atomicState?.curForecast /* || !atomicState?.curAstronomy */ ))) { if(custLoc) { - loc = custLoc - curForecast = getWeatherFeature("forecast", loc) - curAstronomy = getWeatherFeature("astronomy", loc) + loc = custLoc.toString() + curForecast = getTwcForecast(/*loc*/) //getWeatherFeature("forecast", loc) // getTwcForecast(loc) + //curAstronomy = getWeatherFeature("astronomy", loc) // getTwcForecast(loc) } else { - curForecast = getWeatherFeature("forecast") - curAstronomy = getWeatherFeature("astronomy") + curForecast = getTwcForecast() //getWeatherFeature("forecast") // getTwcForecast() + //curAstronomy = getWeatherFeature("astronomy") // getTwcForecast() } - if(curForecast && curAstronomy) { - atomicState?.curForecast = curForecast - atomicState?.curAstronomy = curAstronomy - atomicState?.lastForecastUpdDt = getDtNow() + if(curForecast /*&& curAstronomy*/) { + if(storageApp) { + updStorageVal("curForecast", curForecast) + //updStorageVal("curAstronomy", curAstronomy) + } else { + atomicState?.curForecast = curForecast + //atomicState?.curAstronomy = curAstronomy + } + chgd = true + updTimestampMap("lastForecastUpdDt", getDtNow()) } else { - LogAction("Could Not Retrieve Local Forecast or astronomy Conditions", "warn", true) + LogAction("Could Not Retrieve Local Forecast or astronomy Conditions... This issue is likely caused by Weather Underground API issues...", "warn", true) + atomicState.forceChildUpd = true err = true } } - if(curWeather && curAlerts) { - atomicState?.curWeather = curWeather - atomicState?.curAlerts = curAlerts - if(!err) { atomicState?.lastWeatherUpdDt = getDtNow() } + //if(curWeather && curAlerts) { + if(curWeather) { + if(storageApp) { + updStorageVal("curWeather", curWeather) + updStorageVal("curLocation", curLocation) + } else { + atomicState?.curWeather = curWeather + atomicState?.curLocation = curLocation + } + chgd = true +/* + Try to reduce size of alerts if they are big to save state space +*/ +/* + def alrt = curAlerts?.alerts + def cntr = 0 + alrt.each { al -> + if(al?.message) { + curAlerts.alerts[cntr].message = al.message.take(800) + } + cntr++ + } +ERS todo curAlertdetail = "" + curAlertdetail = getTwcAlertDetail(alertId) +*/ + if(storageApp) { + updStorageVal("curAlerts", curAlerts) + } else { + atomicState?.curAlerts = curAlerts + } + + if(!err) { updTimestampMap("lastWeatherUpdDt", getDtNow()) } } else { - LogAction("Could Not Retrieve Local Weather Conditions or alerts", "warn", true) + LogAction("Could Not Retrieve Local Weather Conditions or alerts... This issue is likely caused by Weather Underground API issues...", "warn", true) + atomicState.forceChildUpd = true return false } - if(curWeather || curAstronomy || curForecast || curAlerts) { + if(chgd) { atomicState.needChildUpd = true if(!force) { runIn(21, "finishPoll", [overwrite: true]) } return true @@ -5784,48 +6179,56 @@ def getWeatherConditions(force = false) { } else { return false } } -def getWData() { - if(atomicState?.curWeather) { - return atomicState?.curWeather +def getWeatherData(dataName) { + def storageApp = getStorageApp(false) + def stateSz = getStateSizePerc() + def t1 = isAppLiteMode() + if(storageApp && (stateSz < 33 || t1)) { + initStorageApp() // should delete storageapp + storageApp = null + } + //storageApp = getStorageApp() + if(storageApp && !t1) { + def t0 = findStateStorageVal(dataName) + if(t0) { + return t0 + } else { if(getWeatherConditions(true)) { return getStorageVal(dataName) } } } else { - if(getWeatherConditions(true)) { - return atomicState?.curWeather + if(stateSz > 62) { + LogAction("storageApp not found getWeatherData ${stateSz}%", "warn", true) + } + if(!t1) { + if(stateSz > 62) { + initStorageApp() // should create storage App + } } + if(atomicState?."$dataName") { + return atomicState?."$dataName" + } else { if(getWeatherConditions(true)) { return atomicState?."$dataName" } } } return null } +def getWLocation() { + return getWeatherData("curLocation") // getTwcConditions() +} + +def getWData() { + return getWeatherData("curWeather") // getTwcConditions() +} + def getWForecastData() { - if(atomicState?.curForecast) { - return atomicState?.curForecast - } else { - if(getWeatherConditions(true)) { - return atomicState?.curForecast - } - } - return null + return getWeatherData("curForecast") // getTwcForecast() } +/* def getWAstronomyData() { - if(atomicState?.curAstronomy) { - return atomicState?.curAstronomy - } else { - if(getWeatherConditions(true)) { - return atomicState?.curAstronomy - } - } - return null + return getWeatherData("curAstronomy") } +*/ def getWAlertsData() { - if(atomicState?.curAlerts) { - return atomicState?.curAlerts - } else { - if(getWeatherConditions(true)) { - return atomicState?.curAlerts - } - } - return null + return getWeatherData("curAlerts") // getTwcAlerts } def getWeatherDeviceInst() { @@ -5833,18 +6236,18 @@ def getWeatherDeviceInst() { } def getWebFileData(now = true) { - //LogTrace("getWebFileData") - def params = [ uri: "https://raw.githubusercontent.com/${gitPath()}/Data/appData.json", contentType: 'application/json' ] + LogTrace("getWebFileData $now") + def params = [ uri: getAppSettingsUrl(), contentType: 'application/json' ] def result = false try { def allowAsync = false def metstr = "sync" - if(!now && atomicState?.appData && atomicState?.appData?.pollMethod?.allowAsync) { + if(!now) { allowAsync = true metstr = "async" } - LogTrace("getWebFileData: Getting appData.json File(${metstr})") + LogTrace("getWebFileData: Getting appConfig.json File(${metstr})") if(now || !allowAsync) { httpGet(params) { resp -> @@ -5856,7 +6259,7 @@ def getWebFileData(now = true) { } catch (ex) { if(ex instanceof groovyx.net.http.HttpResponseException) { - LogAction("appData.json file not found", "warn", true) + LogAction("appConfig.json file not found", "warn", true) } else { log.error "getWebFileData Exception:", ex } @@ -5877,34 +6280,35 @@ def webResponse(resp, data) { //LogTrace("webResponse Resp: ${newdata}") LogTrace("webResponse appData: ${t0}") if(newdata && t0 != newdata) { - LogAction("appData.json File HAS Changed", "info", true) + LogAction("appConfig.json File HAS Changed", "info", true) atomicState?.appData = newdata clientBlacklisted() + clientMetricBlacklisted() + clientExceptionsBlacklisted() updateHandler() - helpHandler() setStateVar(true) - } else { LogAction("appData.json did not change", "info", false) } - if(atomicState?.appData && !appDevType() && atomicState?.clientBlacklisted) { + } else { LogAction("appConfig.json did not change", "info", false) } + if(atomicState?.appData && !appDevType() && atomicState?.cltBlacklisted) { appUpdateNotify() } - if(atomicState?.appData?.appSettings?.pullFromFB == true) { + if(atomicState?.appData?.settings?.database?.pullSettingsFromFB == true) { getFbAppSettings(data?.type == "async" ? false : true ) } - atomicState?.lastWebUpdDt = getDtNow() + updTimestampMap("lastWebUpdDt", getDtNow()) result = true } else { - LogAction("Get failed appData.json status: ${resp?.status}", "warn", true) + LogAction("Get failed appConfig.json status: ${resp?.status}", "warn", true) } return result } def getFbAppSettings(now = true) { - def params = [ uri: "https://st-nest-manager.firebaseio.com/appSettings.json", contentType: 'application/json' ] + def params = [ uri: getAppSettingsFBUrl(), contentType: 'application/json' ] def result = false try { def allowAsync = false def metstr = "sync" - if(!now && atomicState?.appData && atomicState?.appData?.pollMethod?.allowAsync) { + if(!now) { allowAsync = true metstr = "async" } @@ -5920,7 +6324,7 @@ def getFbAppSettings(now = true) { } catch (ex) { if(ex instanceof groovyx.net.http.HttpResponseException) { - //log.warn "clientData.json file not found..." + //log.warn "clientData.json file not found..." } else { LogAction("getFbAppSettings Exception: ${ex}", "error", true) } @@ -5968,30 +6372,44 @@ def getWebData(params, desc, text=true) { } } -def clientBlacklisted() { - if(atomicState?.clientBlacklisted == null) { atomicState?.clientBlacklisted == false } - def curBlState = atomicState?.clientBlacklisted - if(atomicState?.isInstalled && atomicState?.appData?.clientBL) { - def clientList = atomicState?.appData?.clientBL?.clients - if(clientList != null || clientList != []) { - def isBL = (atomicState?.installationId in clientList) ? true : false - if(curBlState != isBL) { - atomicState?.clientBlacklisted = isBL - } - } else { atomicState?.clientBlacklisted = false } - } else { atomicState?.clientBlacklisted = false } +private clientBlacklisted() { + Boolean isBl = false + List clList = atomicState?.appData?.blacklists?.clients ?: [] + if(atomicState?.isInstalled && atomicState?.installationId && clList?.size()) { + isBl = (atomicState?.installationId in clList) + } + atomicState?.cltBlacklisted = isBl +} + +private clientMetricBlacklisted() { + Boolean isBl = false + List clList = atomicState?.appData?.blacklists?.metrics ?: [] + if(atomicState?.isInstalled && clList?.size()) { + isBl = (atomicState?.installationId in clList) + } + atomicState?.cltMetBlacklisted = isBl +} + +private clientExceptionsBlacklisted() { + Boolean isBl = false + List clList = atomicState?.appData?.blacklists?.exceptions ?: [] + if(atomicState?.isInstalled && clList?.size()) { + isBl = (atomicState?.installationId in clList) + } + atomicState?.cltExcBlacklisted = isBl } -def broadcastCheck() { - def bCastData = atomicState?.appData?.broadcast +private broadcastCheck() { + LogTrace("broadcastCheck") + Map bCastData = atomicState?.appData?.broadcast if(atomicState?.isInstalled && bCastData) { - if(bCastData?.msgId != null && atomicState?.lastBroadcastId != bCastData?.msgId) { + if(bCastData?.msgId != "" && bCastData?.message != "" && atomicState?.lastBroadcastId && atomicState?.lastBroadcastId != bCastData?.msgId && (bCastData?.minVer == "" || bCastData?.minVer != appVersion())) { if(sendMsg(strCapitalize(bCastData?.type), bCastData?.message.toString(), true, null, null, null, true)) { atomicState?.lastBroadcastId = bCastData?.msgId } } if(bCastData?.devBannerMsg != null && atomicState?.devBannerData?.msgId != bCastData?.devBannerMsg?.msgId) { - if(bCastData?.devBannerMsg?.msgId && bCastData?.devBannerMsg?.message && bCastData?.devBannerMsg?.type && bCastData?.devBannerMsg?.expireDt) { + if(bCastData?.devBannerMsg?.msgId && bCastData?.devBannerMsg?.message && bCastData?.devBannerMsg?.type && bCastData?.devBannerMsg?.expireDt && (bCastData?.devBannerMsg?.minVer == "" || bCastData?.devBannerMsg?.minVer != appVersion())) { def curDt = Date.parse("E MMM dd HH:mm:ss z yyyy", getDtNow()) def expDt = Date.parse("E MMM dd HH:mm:ss z yyyy", bCastData?.devBannerMsg?.expireDt.toString()) //log.debug "curDt: $curDt | expDt: $expDt | isExpired: ${(curDt > expDt)}" @@ -6003,30 +6421,9 @@ def broadcastCheck() { } } -def helpHandler() { - if(atomicState?.appData?.help) { - atomicState.showHelp = (atomicState?.appData?.help?.showHelp == false) ? false : true - } -} - -def getHtmlInfo() { - if(atomicState?.appData?.html?.cssUrl && atomicState?.appData?.html?.cssVer && atomicState?.appData?.html?.chartJsUrl && atomicState?.appData?.html?.chartJsVer ) { - return ["cssUrl":atomicState?.appData?.html?.cssUrl, "cssVer":atomicState?.appData?.html?.cssVer, "chartJsUrl":atomicState?.appData?.html?.chartJsUrl, "chartJsVer":atomicState?.appData?.html?.chartJsVer] - } else { - if(getWebFileData()) { - return ["cssUrl":atomicState?.appData?.html?.cssUrl, "cssVer":atomicState?.appData?.html?.cssVer, "chartJsUrl":atomicState?.appData?.html?.chartJsUrl, "chartJsVer":atomicState?.appData?.html?.chartJsVer] - } - } -} - def allowDbException() { - if(atomicState?.appData?.database?.disableExceptions != null) { - return atomicState?.appData?.database?.disableExceptions == true ? false : true - } else { - if(getWebFileData()) { - return atomicState?.appData?.database?.disableExceptions == true ? false : true - } - } + if(atomicState?.appData?.settings?.database?.sendExceptions == null) { getWebFileData() } + return (atomicState?.appData?.settings?.database?.sendExceptions == true) } def ver2IntArray(val) { @@ -6034,18 +6431,18 @@ def ver2IntArray(val) { return [maj:"${ver[0]?.toInteger()}",min:"${ver[1]?.toInteger()}",rev:"${ver[2]?.toInteger()}"] } -def versionStr2Int(str) { return str ? str.toString().replaceAll("\\.", "").toInteger() : null } +Integer versionStr2Int(str) { return str ? str.toString()?.replaceAll("\\.", "")?.toInteger() : null } -def getChildWaitVal() { return settings?.tempChgWaitVal ? settings?.tempChgWaitVal.toInteger() : 4 } +Integer getChildWaitVal() { return settings?.tempChgWaitVal ? settings?.tempChgWaitVal.toInteger() : 4 } def getAskAlexaMQEn() { - if(atomicState?.appData?.aaPrefs?.enAaMsgQueue == true) { + if(atomicState?.appData?.settings?.askAlexa?.enAaMsgQueue == true) { return settings?.allowAskAlexaMQ == null ? true : setting?.allowAskAlexaMQ } else { return false } } def getAskAlexaMultiQueueEn() { - return atomicState?.appData?.aaPrefs?.enMultiQueue == true ? true : false + return atomicState?.appData?.settings?.askAlexa?.enMultiQueue == true ? true : false } def initAppMetricStore() { @@ -6083,7 +6480,7 @@ def isCodeUpdateAvailable(newVer, curVer, type) { result = (latestVer == newVer) ? true : false } } - LogTrace("isCodeUpdateAvailable: type: $type | newVer: $newVer | curVer: $curVer | newestVersion: ${latestVer} | result: $result") + //LogTrace("isCodeUpdateAvailable: type: $type | newVer: $newVer | curVer: $curVer | newestVersion: ${latestVer} | result: $result") return result } @@ -6124,20 +6521,19 @@ def isWeatherUpdateAvail() { } def isStreamUpdateAvail() { - if(isCodeUpdateAvailable(atomicState?.appData?.eventStreaming?.minVersion, atomicState?.swVer?.streamDevVer, "stream")) { return true } + if(isCodeUpdateAvailable(atomicState?.appData?.updater?.versions?.stream?.ver, atomicState?.swVer?.streamDevVer, "stream")) { return true } return false } def reqSchedInfoRprt(child, report=true) { - LogTrace("reqSchedInfoRprt: (${child.device.label})") + LogTrace("reqSchedInfoRprt: (${child.device.label}, $report)") def result = null - if(!atomicState?.installData?.usingNewAutoFile) { return result } def tstat = getChildDevice(child.device.deviceNetworkId) if (tstat) { def str = "" def tstatAutoApp = getChildApps()?.find { - (it.getAutomationType() == "schMot" && it?.getTstatAutoDevId() == tstat?.deviceNetworkId) + (it?.getAutomationType() == "schMot" && it?.getTstatAutoDevId() == tstat?.deviceNetworkId) } //LogTrace("tstatAutoApp: ${tstatAutoApp}") def actSchedNum @@ -6161,14 +6557,16 @@ def reqSchedInfoRprt(child, report=true) { if(!report) { def useMot = (schedMotionActive && (schedData?.mctemp || schedData?.mhtemp)) ? true : false tempSrcStr = useMot ? "Schedule Motion Trigger" : tempSrcStr + return ["scdNum":actSchedNum, "schedName":schedData?.lbl, "reqSenHeatSetPoint":reqSenHeatSetPoint, "reqSenCoolSetPoint":reqSenCoolSetPoint, "curZoneTemp":curZoneTemp, "tempSrc":tempSrc, "tempSrcDesc":tempSrcStr] + } else { def tempScaleStr = " degrees" - def canHeat = tstat?.currentCanHeat.toString() == "true" ? true : false - def canCool = tstat?.currentCanCool.toString() == "true" ? true : false - def curMode = tstat?.currentnestThermostatMode.toString() - def curOper = tstat?.currentThermostatOperatingState.toString() - def curHum = tstat?.currentHumidity.toString() + def canHeat = tstat?.currentCanHeat?.toString() == "true" ? true : false + def canCool = tstat?.currentCanCool?.toString() == "true" ? true : false + def curMode = tstat?.currentnestThermostatMode?.toString() + def curOper = tstat?.currentThermostatOperatingState?.toString() + def curHum = tstat?.currentHumidity?.toString() def schedDesc = schedVoiceDesc(actSchedNum, schedData, schedMotionActive) str += schedDesc ?: " There are No Schedules currently Active. " @@ -6186,7 +6584,7 @@ def reqSchedInfoRprt(child, report=true) { else if(zTmp < adj_temp(60.0)) { str += "a freezing " } str += "${curZoneTemp}${tempScaleStr}" str += curHum ? " with a humidity of ${curHum}%. " : ". " - if(zTmp < adj_temp(60.0)) { str += " (Please remember to dress warmly). " } + if(zTmp < adj_temp(60.0)) { str += " (Please remember to dress warmly)." } } } @@ -6210,10 +6608,11 @@ def reqSchedInfoRprt(child, report=true) { } } } else { - //LogAction ("reqSchedInfoRprt: No Automation Schedules were found for ${tstat} device", "warn", false) + LogTrace("reqSchedInfoRprt: No Automation Schedules were found for ${tstat} device") if(report) { result = "No Thermostat Automation Schedules were found for ${tstat} device" } + result = [:] } } else { LogAction("reqSchedInfoRprt: Thermostat device not found", "error", true) @@ -6240,7 +6639,7 @@ def getVoiceRprtCnt() { def schedVoiceDesc(num, data, motion) { def str = "" - str += data?.lbl ? " The automation schedule slot ${num} labeled ${data?.lbl} is currently active. " : "" + str += data?.lbl ? " The automation schedule slot ${num} labeled ${data?.lbl} is currently active. " : "" str += (!motion && (data?.ctemp || data?.htemp)) ? "The schedules desired temps" : "" str += (motion && (data?.mctemp || data?.mhtemp)) ? "The schedules desired motion triggered temps" : "" str += ((motion && data?.mhtemp) || (!motion && data?.htemp)) ? " are set to a heat temp of ${!motion ? fixTempSetting(data?.htemp) : fixTempSetting(data?.mhtemp)} degrees" : "" @@ -6254,12 +6653,12 @@ def schedVoiceDesc(num, data, motion) { | It also Adds Removes Devices from ST | *************************************************************************************************/ -def getNestStructures() { +def getNestStructures(force = false) { LogTrace("Getting Nest Structures") def struct = [:] def thisstruct = [:] try { - if(ok2PollStruct()) { getApiData("str") } + if(ok2PollStruct() || force) { getApiData("str") } if(atomicState?.structData) { def structs = atomicState?.structData structs?.eachWithIndex { struc, index -> @@ -6286,8 +6685,8 @@ def getNestStructures() { if(atomicState?.thermostats || atomicState?.protects || atomicState?.cameras || atomicState?.vThermostats || atomicState?.presDevice || atomicState?.weatherDevice || isAutoAppInst() ) { // if devices are configured, you cannot change the structure until they are removed struct = thisstruct } - if(ok2PollDevice()) { getApiData("dev") } - } else { LogAction("Missing: structData ${atomicState?.structData}", "warn", true) } + if(ok2PollDevice() || force) { getApiData("dev") } + } else { LogAction("Missing: structData ${atomicState?.structData}", "warn", true) } } catch (ex) { log.error "getNestStructures Exception:", ex @@ -6393,14 +6792,20 @@ def camState(val) { def getThermostatDisplayName(stat) { if(stat?.name) { return stat.name.toString() } + else if(stat?.name_long) { return stat?.name_long.toString() } + else { return "Thermostatnamenotfound" } } def getProtectDisplayName(prot) { if(prot?.name) { return prot.name.toString() } + else if(prot?.name_long) { return prot?.name_long.toString() } + else { return "Protectnamenotfound" } } def getCameraDisplayName(cam) { if(cam?.name) { return cam.name.toString() } + else if(cam?.name_long) { return cam?.name_long.toString() } + else { return "Cameranamenotfound" } } def getNestDeviceDni(dni, type) { @@ -6413,7 +6818,7 @@ def getNestDeviceDni(dni, type) { def t0 = "Nest${type}-${dni?.value.toString()}${appDevName()} | ${dni?.key.toString()}" d1 = getChildDevice(t0) if(d1) { retVal = t0.toString() } - retVal = dni?.key.toString() + retVal = dni?.key.toString() } //LogAction("getNestDeviceDni ($type) Issue", "warn", true) //LogAction("getNestDeviceDni: retVal: $retVal", "trace", true) @@ -6439,7 +6844,7 @@ def getNestPresId() { if(d3) { return dni } } def retVal = "" - def devt = appDevName() + def devt = appDevName() if(atomicState?.structures) { retVal = "NestPres${devt} | ${atomicState?.structures}" } else if(settings?.structures) { retVal = "NestPres${devt} | ${settings?.structures}" } else { @@ -6566,7 +6971,7 @@ def getNestWeatherLabel() { def getChildDeviceLabel(dni) { if(!dni) { return null } - return getChildDevice(dni.toString()).getLabel() ?: null + return getChildDevice(dni.toString())?.getLabel() ?: null } def getTstats() { @@ -6614,6 +7019,10 @@ def getLocHub() { def addRemoveDevices(uninst = null) { LogTrace("addRemoveDevices") def retVal = false + if( /* atomicState?.resetAllData ||*/ settings?.resetAllData) { + LogAction("addRemoveDevices: found fixState in progress", "debug", true) + return true + } try { def devsInUse = [] def tstats @@ -6688,8 +7097,8 @@ def addRemoveDevices(uninst = null) { def d4Label = getNestWeatherLabel() d4 = addChildDevice(app.namespace, getWeatherChildName(), dni, null, [label: "${d4Label}"]) //d4.take() - atomicState?.lastWeatherUpdDt = null - atomicState?.lastForecastUpdDt = null + updTimestampMap("lastWeatherUpdDt", null) + updTimestampMap("lastForecastUpdDt", null) devsCrt = devsCrt + 1 LogAction("Created: ${d4.displayName} with (Id: ${dni})", "debug", true) } else { @@ -6719,7 +7128,7 @@ def addRemoveDevices(uninst = null) { } if(atomicState?.vThermostats) { nVstats = atomicState?.vThermostats.collect { dni -> - LogAction("atomicState.vThermostats: ${atomicState.vThermostats} dni: ${dni} dni.key: ${dni.key.toString()} dni.value: ${dni.value.toString()}", "debug", true) + LogAction("atomicState.vThermostats: ${atomicState.vThermostats} dni: ${dni} dni.key: ${dni.key.toString()} dni.value: ${dni.value.toString()}", "debug", true) def d6 = getChildDevice(getNestvStatDni(dni).toString()) if(!d6) { def d6Label = getNestVtstatLabel("${dni.value}", "${dni.key}") @@ -6742,7 +7151,8 @@ def addRemoveDevices(uninst = null) { if(atomicState?.weatherDevice) { weathCnt = 1 } if(devsCrt > 0) { noCreates = false - LogAction("Created Devices; Current Devices: (${tstats?.size()}) Thermostat(s), (${nVstats?.size() ?: 0}) Virtual Thermostat(s), (${nProtects?.size() ?: 0}) Protect(s), (${nCameras?.size() ?: 0}) Cameras(s), ${presCnt} Presence Device and ${weathCnt} Weather Device", "debug", true) + LogAction("Created Devices; Current Devices: (${tstats?.size()}) Thermostat(s), (${nVstats?.size() ?: 0}) Virtual Thermostat(s), (${nProtects?.size() ?: 0}) Protect(s), (${nCameras?.size() ?: 0}) Cameras(s), ${presCnt} Presence Device and ${weathCnt} Weather Device", "debug", true) + updTimestampMap("lastAnalyticUpdDt", null) } } @@ -6756,9 +7166,10 @@ def addRemoveDevices(uninst = null) { } if(!atomicState?.weatherDevice) { + runIn(5, "cleanStorage", [overwrite: true]) // calling the child truncates logs atomicState?.curWeather = null atomicState?.curForecast = null - atomicState?.curAstronomy = null + //atomicState?.curAstronomy = null atomicState?.curAlerts = null } @@ -6770,21 +7181,22 @@ def addRemoveDevices(uninst = null) { if(delete?.size() > 0) { noDeletes = false noDeleteErr = false + updTimestampMap("lastAnalyticUpdDt", null) LogAction("Removing ${delete.size()} devices: ${delete}", "debug", true) - delete.each { deleteChildDevice(it.deviceNetworkId) } + delete.each { deleteChildDevice(it.deviceNetworkId, true) } noDeleteErr = true } - retVal = ((unist && noDeleteErr) || (!uninst && (noCreates && noDeletes))) ? true : false // it worked = no delete errors on uninstall; or no creates or deletes done + retVal = ((uninst && noDeleteErr) || (!uninst && (noCreates && noDeletes))) ? true : false // it worked = no delete errors on uninstall; or no creates or deletes done //retVal = true //currentDevMap(true) } catch (ex) { if(ex instanceof physicalgraph.exception.ConflictException) { - def msg = "Error: Can't Remove Device. One or more of them are still in use by other SmartApps or Routines. Please remove them and try again!" + def msg = "Error: Can't Remove Device. One or more of them are still in use by other SmartApps or Routines. Please remove them and try again!" sendPush(msg) LogAction("addRemoveDevices Exception | $msg", "warn", true) } else if(ex instanceof physicalgraph.app.exception.UnknownDeviceTypeException) { - def msg = "Error: Device Handlers are Missing or Not Published. Please verify all device handlers are present before continuing." + def msg = "Error: Device Handlers are Missing or Not Published. Please verify all device handlers are present before continuing." appUpdateNotify() sendPush(msg) LogAction("addRemoveDevices Exception | $msg", "warn", true) @@ -6798,23 +7210,9 @@ def addRemoveDevices(uninst = null) { return retVal } -/* -def setMyLockId(val) { - if(atomicState?.myID == null && parent && val) { - atomicState.myID = val - } -} -*/ - -def getMyLockId() { - if(parent) { return atomicState?.myID } else { return null } -} - - - def addRemoveVthermostat(tstatdni, tval, myID) { def odevId = tstatdni - LogAction("addRemoveVthermostat() tstat: ${tstatdni} devid: ${odevId} tval: ${tval} myID: ${myID} vThermostats: ${atomicState?.vThermostats} ", "trace", true) + LogAction("addRemoveVthermostat() tstat: ${tstatdni} devid: ${odevId} tval: ${tval} myID: ${myID} vThermostats: ${atomicState?.vThermostats} ", "trace", true) if(parent || !myID || tval == null) { LogAction("got called BADLY ${parent} ${myID} ${tval}", "warn", true) @@ -6835,9 +7233,10 @@ def addRemoveVthermostat(tstatdni, tval, myID) { def devId = "v${odevId}" - def migrate = migrationInProgress() + // def migrate = migrationInProgress() - if(!migrate && atomicState?."vThermostat${devId}" && myID != atomicState?."vThermostatChildAppId${devId}") { + // if(!migrate && atomicState?."vThermostat${devId}" && myID != atomicState?."vThermostatChildAppId${devId}") { + if(atomicState?."vThermostat${devId}" && myID != atomicState?."vThermostatChildAppId${devId}") { LogAction("addRemoveVthermostat() not ours ${myID} ${atomicState?."vThermostat${devId}"} ${atomicState?."vThermostatChildAppId${devId}"}", "trace", true) //atomicState?."vThermostat${devId}" = false //atomicState?."vThermostatChildAppId${devId}" = null @@ -6862,7 +7261,7 @@ def addRemoveVthermostat(tstatdni, tval, myID) { def vtlist = atomicState?.vThermostats ?: [:] vtlist[devId] = "${tstat.label.toString()}" atomicState.vThermostats = vtlist - if(!migrate) { runIn(10, "updated", [overwrite: true]) } // create what is needed + if(!settings?.resetAllData) { runIn(120, "updated", [overwrite: true]) } // create what is needed } else if(!tval && atomicState?."vThermostatChildAppId${devId}") { LogAction("addRemoveVthermostat() marking for remove virtual thermostat tracking ${tstat}", "trace", true) @@ -6886,7 +7285,7 @@ def addRemoveVthermostat(tstatdni, tval, myID) { } vtlist = newlist atomicState.vThermostats = vtlist - if(!migrate) { runIn(10, "updated", [overwrite: true]) } // create what is needed + if(!settings?.resetAllData) { runIn(120, "updated", [overwrite: true]) } // create what is needed } else { LogAction("addRemoveVthermostat() unexpected operation state ${myID} ${atomicState?."vThermostat${devId}"} ${atomicState?."vThermostatChildAppId${devId}"}", "warn", true) return false @@ -6908,7 +7307,7 @@ def deviceHandlerTest() { def preReqCheck() { //LogTrace("preReqCheckTest()") - if(!atomicState?.installData) { atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString(), "updatedDt":"Not Set", "freshInstall":true, "shownDonation":false, "shownFeedback":false, "shownChgLog":true, "usingNewAutoFile":true] } + if(!atomicState?.installData) { atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString(), "updatedDt":"Not Set", "freshInstall":true, "shownDonation":false, "shownFeedback":false, "shownChgLog":true, "usingNewAutoFile":true, "liteAppMode":isAppLiteMode()] } if(!location?.timeZone || !location?.zipCode) { atomicState.preReqTested = false LogAction("SmartThings Location not returning (TimeZone: ${location?.timeZone}) or (ZipCode: ${location?.zipCode}) Please edit these settings under the IDE", "warn", true) @@ -6944,21 +7343,27 @@ def getAccessToken() { else { return true } } catch (ex) { - def msg = "Error: OAuth is not Enabled for ${appName()}!. Please click remove and Enable Oauth under the SmartApp App Settings in the IDE" + def msg = "Error: OAuth is not Enabled for ${appName()}!. Please click remove and Enable Oauth under the SmartApp App Settings in the IDE" sendPush(msg) log.error "getAccessToken Exception", ex LogAction("getAccessToken Exception | $msg", "warn", true) - sendExceptionData(ex, "getAccessToken") + //sendExceptionData(ex, "getAccessToken") return false } } -void resetSTAccessToken() { +void resetSTAccessToken(reset) { + if(reset != true) { return } LogAction("Resetting SmartApp Access Token....", "info", true) - restStreamHandler(true) - atomicState?.restStreamingOn = false + atomicState?.pollBlocked = true + atomicState?.pollBlockedReason = "reseting Access Token" + restStreamHandler(true, false) + //atomicState?.restStreamingOn = false revokeAccessToken() atomicState?.accessToken = null + atomicState?.pollBlocked = false + atomicState?.pollBlockedReason = "" + if(getAccessToken()) { LogAction("Reset SmartApp Access Token... Successful", "info", true) settingUpdate("resetSTAccessToken", "false", "bool") @@ -7006,7 +7411,7 @@ def callback() { httpPost(uri: tokenUrl) { resp -> atomicState.authToken = resp?.data.access_token if(atomicState?.authToken) { - atomicState?.authTokenCreatedDt = getDtNow() + updTimestampMap("authTokenCreatedDt", getDtNow()) atomicState.authTokenExpires = resp?.data.expires_in // atomicState.authTokenNum = clientToken() atomicState.oauthInitState = UUID?.randomUUID().toString() @@ -7019,7 +7424,6 @@ def callback() { atomicState?.needDevPoll = true atomicState?.needMetaPoll = true runIn(5, "finishRemap", [overwrite: true]) - success() } else { @@ -7034,26 +7438,27 @@ def callback() { } } -// ERSERS check remapping def finishRemap() { - checkRemapping() - atomicState.needToFinalize = true - runIn(21, "finalizeRemap", [overwrite: true]) + LogTrace("finishRemap (${atomicState?.pollBlocked}) (${atomicState?.pollBlockedReason})") + checkRemapping() + atomicState.needToFinalize = true + runIn(21, "finalizeRemap", [overwrite: true]) } def finalizeRemap() { - fixDevAS() - sendInstallSlackNotif(false) - atomicState.needToFinalize = false - initManagerApp() - state.remove("needToFinalize") + LogTrace("finalizeRemap (${atomicState?.pollBlocked}) (${atomicState?.pollBlockedReason})") + fixDevAS() + //sendInstallSlackNotif(false) + atomicState.needToFinalize = false + initManagerApp() + state.remove("needToFinalize") } def revokeNestToken() { if(atomicState?.authToken) { LogAction("revokeNestToken()", "info", true) - restStreamHandler(true) - atomicState?.restStreamingOn = false + restStreamHandler(true, false) + //atomicState?.restStreamingOn = false def params = [ uri: "https://api.home.nest.com", path: "/oauth2/access_tokens/${atomicState?.authToken}", @@ -7085,16 +7490,18 @@ def revokeNestToken() { def revokeCleanState() { unschedule() atomicState.authToken = null - atomicState.authTokenCreatedDt = null - atomicState.authTokenExpires = getDtNow() + updTimestampMap("authTokenCreatedDt", null) + atomicState.authTokenExpires = null atomicState.structData = null atomicState.deviceData = null atomicState.metaData = null - atomicState?.lastStrucDataUpd = null - atomicState?.lastDevDataUpd = null - atomicState?.lastMetaDataUpd = null + updTimestampMap("lastStrDataUpd", null) + updTimestampMap("lastDevDataUpd", null) + updTimestampMap("lastMetaDataUpd", null) atomicState?.pollingOn = false + atomicState.streamPolling = false atomicState?.pollBlocked = false + atomicState?.workQrunInActive = false atomicState?.pollBlockedReason = "No Auth Token" } @@ -7102,7 +7509,7 @@ def revokeCleanState() { def success() { def message = """

Your SmartThings Account is now connected to Nest!

-

Click 'Done' to finish setup.

+

Click Done or Next to proceed with the rest of the setup.

""" connectionStatus(message) } @@ -7110,7 +7517,7 @@ def success() { def fail() { def message = """

The connection could not be established!

-

Click 'Done' to return to the menu.

+

Click Done or Next to return to the menu.

""" connectionStatus(message) } @@ -7118,67 +7525,19 @@ def fail() { def connectionStatus(message, redirectUrl = null) { def redirectHtml = "" if(redirectUrl) { redirectHtml = """""" } - def html = """ - - SmartThings & Nest connection - + + SmartThings & Nest connection + -
- - connected device icon - +
+

+

+ ${message}
@@ -7196,25 +7555,46 @@ def toQueryString(Map m) { return m.collect { k, v -> "${k}=${URLEncoder.encode(v.toString())}" }.sort().join("&") } -def clientId() { - if(appSettings?.clientId) { - return appSettings?.clientId +Map devClientData() { + if(!atomicState?.appData?.other) { updateWebStuff(true) } + Map m = atomicState?.appData?.other ?: [:] + // log.debug "m: ${m}" + def clt = m?.active ?: 0 + def id = m?.items[clt]?.id?.decodeBase64() + def secret = m?.items[clt]?.secret?.decodeBase64() + return [id: new String(id), secret: new String(secret)] +} + +//These are the Nest OAUTH Methods to aquire the auth code and then Access Token. +String clientId() { + if(appSettings?.clientId && appSettings?.clientId != "blank") { + return appSettings?.clientId?.toString().trim() } else { - LogAction("clientId is missing and is required to generate your Nest Auth token. Please verify you are running the latest software version", "error", true) + if(devClientData()) { + return devClientData()?.id ?: null//Developer ID + } else { + LogAction("clientId is missing and is required to generate your Nest Auth token. Please verify you are running the latest software version", "error", true) + } return null } } -def clientSecret() { - if(appSettings?.clientSecret) { - return appSettings?.clientSecret +String clientSecret() { + if(appSettings?.clientSecret && appSettings?.clientSecret != "blank") { + return appSettings?.clientSecret?.toString().trim() } else { - LogAction("clientSecret is missing and is required to generate your Nest Auth token. Please verify you are running the latest software version", "error", true) + if(devClientData()) { + return devClientData()?.secret ?: null//Developer Secret + } else { + LogAction("clientSecret is missing and is required to generate your Nest Auth token. Please verify you are running the latest software version", "error", true) + } return null } } def nestDevAccountCheckOk() { + // log.debug "clientId: ${clientId()}" + // log.debug "clientSecret: ${clientSecret()}" if(atomicState?.authToken == null && (clientId() == null || clientSecret() == null) ) { return false } else { return true } } @@ -7223,7 +7603,7 @@ def nestDevAccountCheckOk() { | LOGGING AND Diagnostic | *************************************************************************************************/ def LogTrace(msg, logSrc=null) { - def trOn = (appDebug && advAppDebug) ? true : false + def trOn = (settings?.appDebug && settings?.advAppDebug && !settings?.enRemDiagLogging) ? true : false if(trOn) { def logOn = (settings?.enRemDiagLogging && atomicState?.enRemDiagLogging) ? true : false def theLogSrc = (logSrc == null) ? (parent ? "Automation" : "Manager") : logSrc @@ -7232,7 +7612,7 @@ def LogTrace(msg, logSrc=null) { } def LogAction(msg, type="debug", showAlways=false, logSrc=null) { - def isDbg = appDebug ? true : false + def isDbg = (settings?.appDebug && !settings?.enRemDiagLogging) ? true : false def theLogSrc = (logSrc == null) ? (parent ? "Automation" : "Manager") : logSrc if(showAlways) { Logger(msg, type, theLogSrc) } else if(isDbg && !showAlways) { Logger(msg, type, theLogSrc) } @@ -7248,12 +7628,19 @@ def tokenStrScrubber(str) { } def Logger(msg, type, logSrc=null, noSTlogger=false) { + def labelstr = "" + def logOut = true + if(settings?.debugAppendAppName != false) { labelstr = "${app.label} (v${appVersion()}) | " } if(msg && type) { - def labelstr = "" - if(settings?.debugAppendAppName || settings?.debugAppendAppName == null) { labelstr = "${app.label} | " } def themsg = tokenStrScrubber("${labelstr}${msg}") - if(!noSTlogger) { + if(atomicState?.enRemDiagLogging && settings?.enRemDiagLogging && atomicState?.remDiagAppAvailable == true) { + if(saveLogtoRemDiagStore(themsg, type, logSrc) == true) { + logOut = false + } + } + // log.debug "logOut: $logOut | noSTlogger: $noSTlogger" + if(logOut == true && noSTlogger == false) { switch(type) { case "debug": log.debug "${themsg}" @@ -7276,13 +7663,39 @@ def Logger(msg, type, logSrc=null, noSTlogger=false) { } } //log.debug "Logger remDiagTest: $msg | $type | $logSrc" - saveLogtoRemDiagStore(themsg, type, logSrc) } else { log.error "${labelstr}Logger Error - type: ${type} | msg: ${msg} | logSrc: ${logSrc}" } } +def getDiagLogTimeRemaining() { + return sec2PrettyTime((3600*48) - Math.abs((getRemDiagActSec() ?: 0))) +} + +String sec2PrettyTime(Integer timeSec) { + Integer years = Math.floor(timeSec / 31536000); timeSec -= years * 31536000; + Integer months = Math.floor(timeSec / 31536000); timeSec -= months * 2592000; + Integer days = Math.floor(timeSec / 86400); timeSec -= days * 86400; + Integer hours = Math.floor(timeSec / 3600); timeSec -= hours * 3600; + Integer minutes = Math.floor(timeSec / 60); timeSec -= minutes * 60; + Integer seconds = Integer.parseInt((timeSec % 60) as String, 10); + Map dt = [y: years, mn: months, d: days, h: hours, m: minutes, s: seconds] + String dtStr = "" + // dtStr += dt?.y ? "${dt?.y}yr${dt?.y>1?"s":""}, " : "" + // dtStr += dt?.mn ? "${dt?.mn}mon${dt?.mn>1?"s":""}, " : "" + // dtStr += dt?.d ? "${dt?.d}day${dt?.d>1?"s":""}, " : "" + // dtStr += dt?.h ? "${dt?.h}hr${dt?.h>1?"s":""} " : "" + // dtStr += dt?.m ? "${dt?.m}min${dt?.m>1?"s":""} " : "" + // dtStr += dt?.s ? "${dt?.s}sec" : "" + dtStr += dt?.d ? "${dt?.d}d " : "" + dtStr += dt?.h ? "${dt?.h}h " : "" + dtStr += dt?.m ? "${dt?.m}m " : "" + dtStr += dt?.s ? "${dt?.s}s" : "" + return dtStr +} + def saveLogtoRemDiagStore(String msg, String type, String logSrcType=null, frc=false) { - //log.trace "saveLogtoRemDiagStore($msg, $type, $logSrcType)" + def retVal = false + // log.trace "saveLogtoRemDiagStore($msg, $type, $logSrcType)" if(atomicState?.enRemDiagLogging && settings?.enRemDiagLogging) { def turnOff = false def reasonStr = "" @@ -7291,51 +7704,58 @@ def saveLogtoRemDiagStore(String msg, String type, String logSrcType=null, frc=f turnOff = true reasonStr += "was active for last 48 hours " } - if(!atomicState?.appData?.database?.allowRemoteDiag) { - turnOff = true - reasonStr += "appData does not allow" - } - def remDiagApp = getRemDiagApp() } if(turnOff) { saveLogtoRemDiagStore("Diagnostics disabled due to ${reasonStr}", "info", "Manager", true) diagLogProcChange(false) - LogAction("Remote Diagnostics disabled ${reasonStr}", "info", true) + log.info "Remote Diagnostics disabled ${reasonStr}" } else { if(getStateSizePerc() >= 65) { log.warn "saveLogtoRemDiagStore: remoteDiag log storage suspended state size is ${getStateSizePerc()}%" } else { if(msg) { def data = atomicState?.remDiagLogDataStore ?: [] - def item = ["dt":new Date().getTime(), "type":type, "src":(logSrcType ?: "Not Set"), "msg":msg] + def dt = new Date().getTime() + def item = ["dt":dt, "type":type, "src":(logSrcType ?: "Not Set"), "msg":msg] data << item atomicState?.remDiagLogDataStore = data + retVal = true } } def data = atomicState?.remDiagLogDataStore ?: [] def t0 = data?.size() if(t0 && (t0 > 30 || frc || getLastRemDiagSentSec() > 120 || getStateSizePerc() >= 65)) { + def remDiagApp = getRemDiagApp() if(remDiagApp) { remDiagApp?.savetoRemDiagChild(data) - atomicState?.remDiagDataSentDt = getDtNow() + updTimestampMap("remDiagDataSentDt", getDtNow()) + //atomicState?.remDiagDataSentDt = getDtNow() } else { - //diagLogProcChange(false) log.warn "Remote Diagnostics Child app not found" + if(getRemDiagActSec() > 20) { // avoid race that child did not start yet + diagLogProcChange(false) + } + retVal = false } atomicState?.remDiagLogDataStore = [] } } } + return retVal } def fixState() { def result = false - LogAction("fixState", "info", false) + LogTrace("fixState (${atomicState?.pollBlocked}) (${atomicState?.pollBlockedReason})") def before = getStateSizePerc() if(!parent) { if(!atomicState?.resetAllData && resetAllData) { - def data = getState()?.findAll { !(it?.key in ["accessToken", "authToken", "authTokenExpires", "authTokenCreatedDt", "authTokenNum", "enRemDiagLogging", "installationId", "remDiagLogActivatedDt", "installData", "remDiagLogDataStore", "remDiagDataSentDt", "resetAllData", "pollingOn", "apiCommandCnt", "autoMigrationComplete" ]) } + def data = getState()?.findAll { !(it?.key in ["accessToken", "authToken", "authTokenExpires", "timestampDtMap", "authTokenNum", "enRemDiagLogging", + "installationId", "installData", "remDiagLogDataStore", "remDiagDataSentDt", "resetAllData", "pollingOn", "pollBlocked", "ssdpOn", + "pollBLockedReason", "resetAllData", "autoMigrationComplete", "tsMigration", "savedNestSettings", + "apiCommandCnt", "apiStrReqCnt", "apiDevReqCnt", "apiMetaReqCnt", "apiRestStrEvtCnt", "appNotifSentCnt", "structData", "deviceData", + "disableAllAutomations", "automationNestModeEnabled", "automationNestModeEcoActive" ]) } data.each { item -> state.remove(item?.key.toString()) } @@ -7345,6 +7765,9 @@ def fixState() { atomicState.pollingOn = false atomicState?.pollBlocked = true atomicState?.pollBlockedReason = "Repairing State" + toggleAllAutomations() + updTimestampMap("lastChildUpdDt", getDtNow()) // make sure we don't try to force child update too soon + updTimestampMap("lastDevDataUpd", getDtNow()) result = true } else if(atomicState?.resetAllData && !resetAllData) { LogAction("fixState: resetting ALL toggle", "info", true) @@ -7355,19 +7778,23 @@ def fixState() { if(result) { atomicState.resetAllData = true LogAction("fixState: State Data: before: $before after: ${getStateSizePerc()}", "info", true) - runIn(20, "finishFixState", [overwrite: true]) + runIn(22, "finishFixState", [overwrite: true]) } return result } void finishFixState() { - LogAction("finishFixState", "info", false) + LogTrace("finishFixState (${atomicState?.pollBlocked}) (${atomicState?.pollBlockedReason})") + atomicState?.pollBlockedReason = "finishFixState" if(!parent) { if(atomicState?.resetAllData) { + if(atomicState?.notificationPrefs == null) { atomicState?.notificationPrefs = buildNotifPrefMap() } atomicState.devNameOverride = settings?.devNameOverride ? true : false atomicState.useAltNames = settings?.useAltNames ? true : false atomicState.custLabelUsed = settings?.useCustDevNames ? true : false - if(!atomicState?.installData) { atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString(), "updatedDt":"Not Set", "freshInstall":true, "shownDonation":false, "shownFeedback":false, "shownChgLog":true, "usingNewAutoFile":true] } + if(!atomicState?.installData) { + atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString(), "updatedDt":"Not Set", "freshInstall":true, "shownDonation":false, "shownFeedback":false, "shownChgLog":true, "usingNewAutoFile":true, "liteAppMode":isAppLiteMode()] + } getWebFileData() // get the appData and calls setStateVar @@ -7377,20 +7804,8 @@ void finishFixState() { atomicState.structures = settings?.structures ?: null - def structs = getNestStructures() - -/* initManagerApp will do this - if(settings?.structures && atomicState?.structures && !atomicState.structName) { - if(structs && structs?."${atomicState?.structures}") { - atomicState.structName = "${structs[atomicState?.structures]}" - } - } - //def str = getApiData("str") - //def dev = getApiData("dev") - //def meta = getApiData("meta") -*/ + def structs = getNestStructures(true) -// TODO ERS fixDevAS() if(settings?.thermostats || settings?.protects || settings?.cameras || settings?.presDevice || settings?.weatherDevice) { @@ -7399,16 +7814,8 @@ void finishFixState() { atomicState?.setupVersion = atomicState?.appData?.updater?.setupVersion?.toInteger() ?: 0 } else { atomicState.isInstalled = false } - initManagerApp() - -/* initManagerApp does this - def cApps = getChildApps() - if(cApps) { - cApps?.sort()?.each { chld -> - chld?.update() - } - } -*/ + runIn(21, "initManagerApp", [overwrite: true]) // need to give time for watchdog updates before we try to delete devices. + //initManagerApp() } } else { LogAction("finishFixState called as CHILD", "error", true) @@ -7416,6 +7823,7 @@ void finishFixState() { } def fixDevAS() { + LogTrace("fixDevAS") if(settings?.thermostats && !atomicState?.thermostats) { atomicState.thermostats = settings?.thermostats ? statState(settings?.thermostats) : null } if(settings?.protects && !atomicState?.protects) { atomicState.protects = settings?.protects ? coState(settings?.protects) : null } if(settings?.cameras && !atomicState?.cameras) { atomicState.cameras = settings?.cameras ? camState(settings?.cameras) : null } @@ -7425,18 +7833,21 @@ def fixDevAS() { void settingUpdate(name, value, type=null) { LogAction("settingUpdate($name, $value, $type)...", "trace", false) -// try { - //if(name && value && type) { - if(name && type) { - app?.updateSetting("$name", [type: "$type", value: value]) + if(name) { + if(value == "" || value == null || value == []) { + settingRemove(name) + return } - //else if (name && value && type == null){ app?.updateSetting(name.toString(), value) } - else if (name && type == null){ app?.updateSetting(name.toString(), value) } -/* - } catch(e) { - log.error "settingUpdate Exception:", ex } -*/ + if(name && type) { + app?.updateSetting("$name", [type: "$type", value: value]) + } + else if (name && type == null){ app?.updateSetting(name.toString(), value) } +} + +void settingRemove(name) { + LogAction("settingRemove($name)...", "trace", false) + if(name) { app?.deleteSetting("$name") } } def stateUpdate(key, value) { @@ -7450,15 +7861,27 @@ def setStateVar(frc = false) { //the app to create any new state values that might not exist or reset those that do to prevent errors def stateVer = 3 def stateVar = !atomicState?.stateVarVer ? 0 : atomicState?.stateVarVer.toInteger() - if(!atomicState?.stateVarUpd || frc || (stateVer < atomicState?.appData.state.stateVarVer.toInteger())) { + if(!atomicState?.stateVarUpd || frc || (stateVer < atomicState?.appData?.settings?.maintenance?.stateVer?.toInteger())) { if(!atomicState?.newSetupComplete) { atomicState.newSetupComplete = false } if(!atomicState?.setupVersion) { atomicState?.setupVersion = 0 } if(!atomicState?.custLabelUsed) { atomicState?.custLabelUsed = false } if(!atomicState?.useAltNames) { atomicState.useAltNames = false } if(!atomicState?.apiCommandCnt) { atomicState?.apiCommandCnt = 0L } atomicState?.stateVarUpd = true - atomicState?.stateVarVer = atomicState?.appData?.state?.stateVarVer ? atomicState?.appData?.state?.stateVarVer?.toInteger() : 0 + atomicState?.stateVarVer = atomicState?.appData?.settings?.maintenance?.stateVer ? atomicState?.appData?.settings?.maintenance?.stateVer?.toInteger() : 0 + } +} + +def timestampMigration() { + def items = ["apiIssueDt","authTokenCreatedDt", "cmdLastProcDt", "debugEnableDt", "lastApiIssueMsgDt", "lastChildUpdDt", "lastDevDataUpd", "lastFailedCmdMsgDt", "lastForcePoll", "lastForecastUpdDt", + "lastHeardFromNestDt", "lastMetaDataUpd", "lastMisPollMsgDt", "lastStrDataUpd", "lastUpdMsgDt", "lastUpdateMsgDt", "lastWeatherUpdDt", "lastWebUpdDt", "remDiagLogActivatedDt" + ] + def sData = atomicState?.timestampDtMap ?: [:] + items?.each { item-> + if(sData[item] == null) { sData[item] = state[item] } + state.remove(item) } + atomicState?.tsMigration = true } //Things that need to clear up on updates go here @@ -7467,53 +7890,65 @@ def stateCleanup() { def data = [ "exLogs", "pollValue", "pollStrValue", "pollWaitVal", "tempChgWaitVal", "cmdDelayVal", "testedDhInst", "missedPollNotif", "updateMsgNotif", "updChildOnNewOnly", "disAppIcons", "showProtAlarmStateEvts", "showAwayAsAuto", "cmdQlist", "cmdQ", "recentSendCmd", "cmdIsProc", "currentWeather", "altNames", "locstr", "custLocStr", "autoAppInstalled", "nestStructures", "lastSentExceptionDataDt", - "swVersion", "dashSetup", "dashboardUrl", "apiIssues", "stateSize", "haveRun", "lastStMode", "lastPresSenAway", + "swVersion", "dashSetup", "dashboardUrl", "apiIssues", "stateSize", "haveRun", "lastStMode", "lastPresSenAway", "devCodeIdData", "appCodeIdData", "clientBlacklisted", "automationsActive", "temperatures", "powers", "energies", "use24Time", "useMilitaryTime", "advAppDebug", "appDebug", "awayModes", "homeModes", "childDebug", "updNotifyWaitVal", - "appApiIssuesWaitVal", "misPollNotifyWaitVal", "misPollNotifyMsgWaitVal", "devHealthMsgWaitVal", "nestLocAway", "heardFromRestDt", "autoSaVer", "lastAnalyticUpdDt", "lastHeardFromRestDt", - "remDiagApp", "remDiagClientId", "restorationInProgress", "diagManagAppStateFilters", "diagChildAppStateFilters", "lastFinishedPoll", - "curAlerts", "curAstronomy", "curForecast", "curWeather", "detailEventHistory", "detailExecutionHistory", "evalExecutionHistory", "lastForecastUpdDt", "lastWeatherUpdDt", - "lastMsg", "lastMsgDt", "qFirebaseRequested", "qmetaRequested", "debugAppendAppName" + "appApiIssuesWaitVal", "misPollNotifyWaitVal", "misPollNotifyMsgWaitVal", "devHealthMsgWaitVal", "nestLocAway", "heardFromRestDt", "autoSaVer", "lastHeardFromRestDt", + "remDiagApp", "remDiagClientId", "restorationInProgress", "diagManagAppStateFilters", "diagChildAppStateFilters", "lastFinishedPoll","tDevVer", "pDevVer", "camDevVer", "presDevVer", "weatDevVer", "vtDevVer", "streamDevVer", + /* "curAlerts", */ "curAstronomy", /* "curForecast", "curWeather", */ "detailEventHistory", "detailExecutionHistory", "evalExecutionHistory", "lastForecastUpdDt", "lastWeatherUpdDt", + "lastMsg", "lastMsgDt", "qFirebaseRequested", "qmetaRequested", "debugAppendAppName", "ReallyChanged", "tsMigrationDone", "pushTested", "lastDevHealthMsgData" ] - data.each { item -> - state.remove(item?.toString()) - } - data = [ "tDevVer", "pDevVer", "camDevVer", "presDevVer", "weatDevVer", "vtDevVer", "streamDevVer" ] - def sData = atomicState?.swVer ?: [:] - data.each { item -> + ["oldTstat", "oldvTstat", "oldvStat", "oldCamData", "oldProt", "oldPres", "oldWeather", "lastCmdSentDt", "recentSendCmd" ]?.each { oi-> + def oiRem = state?.findAll { it?.key?.toString().startsWith(oi) }.collect { it?.key } + data = data+oiRem + } + data?.each { item -> + //if(state?.containsKey(item)) { state.remove(item?.toString()) } state.remove(item?.toString()) - sData["${item}"] = null } + atomicState.authTokenExpires = atomicState?.tokenExpires ?: atomicState?.authTokenExpires state.remove("tokenExpires") - atomicState.authTokenCreatedDt = atomicState?.tokenCreatedDt ?: atomicState?.authTokenCreatedDt + updTimestampMap("authTokenCreatedDt", (atomicState?.tokenCreatedDt ?: getTimestampVal("authTokenCreatedDt"))) state.remove("tokenCreatedDt") - atomicState?.swVer = sData - if(!atomicState?.cmdQlist) { - data = [ "cmdQ2", "cmdQ3", "cmdQ4", "cmdQ5", "cmdQ6", "cmdQ7", "cmdQ8", "cmdQ9", "cmdQ10", "cmdQ11", "cmdQ12", "cmdQ13", "cmdQ14", "cmdQ15", "lastCmdSentDt2", "lastCmdSentDt3", - "lastCmdSentDt4", "lastCmdSentDt5", "lastCmdSentDt6", "lastCmdSentDt7", "lastCmdSentDt8", "lastCmdSentDt9", "lastCmdSentDt10", "lastCmdSentDt11", "lastCmdSentDt12", "lastCmdSentDt13", - "lastCmdSentDt14", "lastCmdSentDt15", "recentSendCmd2", "recentSendCmd3", "recentSendCmd4", "recentSendCmd5", "recentSendCmd6", "recentSendCmd7", "recentSendCmd8", "recentSendCmd9", - "recentSendCmd10", "recentSendCmd11", "recentSendCmd12", "recentSendCmd13", "recentSendCmd14", "recentSendCmd15" - ] + data = [ "cmdQ0", "cmdQ1", "cmdQ2", "cmdQ3", "cmdQ4", "cmdQ5", "cmdQ6", "cmdQ7", "cmdQ8", "cmdQ9", "cmdQ10", "cmdQ11", "cmdQ12", "cmdQ13", "cmdQ14", "cmdQ15" ] data.each { item -> + //if(state?.containsKey(item)) { state.remove(item?.toString()) } state.remove(item?.toString()) } } + atomicState?.workQrunInActive = false atomicState.forceChildUpd = true - def sdata = [ "showAwayAsAuto", "temperatures", "powers", "energies", "childDevDataPageDev", "childDevPageRfsh", "childDevDataRfshVal", "childDevDataStateFilter", "childDevPageShowAttr", "childDevPageShowCapab", "childDevPageShowCmds", "childDevPageShowState", - "managAppPageRfsh", "managAppPageShowMeta", "managAppPageShowSet", "managAppPageShowState", "updChildOnNewOnly" + def remSettings = [ "showAwayAsAuto", "temperatures", "powers", "energies", "childDevDataPageDev", "childDevPageRfsh", "childDevDataRfshVal", "childDevDataStateFilter", "childDevPageShowAttr", + "childDevPageShowCapab", "childDevPageShowCmds", "childDevPageShowState", "managAppPageRfsh", "managAppPageShowMeta", "managAppPageShowSet", "managAppPageShowState", "updChildOnNewOnly", + "locDesiredButton", "locDesiredTempScale", "recipients", "enableDashboard" ] - sdata.each { item -> - if(settings?."${item}" != null) { - settingUpdate("${item.toString()}", "") // clear settings + List camMotionSets = settings?.keySet()?.findAll { it?.toString()?.startsWith("camera_") && it?.toString()?.endsWith("_zones") }?.collect { it as String } + if(camMotionSets?.size()) { + if(settings?.camEnMotionZoneFltr) { + atomicState?.cameras?.keySet()?.each { cam-> if(camMotionSets?.find {"camera_${cam}_zones"}) { camMotionSets = camMotionSets - "camera_${cam}_zones" } } } + remSettings = remSettings+camMotionSets + } + remSettings.each { item -> + //if(settings?.containsKey(item)) { + settingRemove(item.toString()) // removes settings + //} } + runIn(25, "cleanStorage", [overwrite: true]) // calling the child truncates logs +} + +def cleanStorage() { + remStorageVal("curForecast") + remStorageVal("curAstronomy") + remStorageVal("curWeather") + remStorageVal("curAlerts") } /****************************************************************************** -* STATIC METHODS * +* STATIC METHODS * *******************************************************************************/ def getThermostatChildName() { return getChildName("Nest Thermostat") } def getProtectChildName() { return getChildName("Nest Protect") } @@ -7522,8 +7957,9 @@ def getWeatherChildName() { return getChildName("Nest Weather") } def getCameraChildName() { return getChildName("Nest Camera") } def getAutoAppChildName() { return getChildName(autoAppName()) } -def getWatDogAppChildName() { return getChildName("Nest Location ${location.name} Watchdog") } -def getRemDiagAppChildName() { return getChildName("NST Diagnostics") } +def getWatDogAppChildLabel() { return getChildName("Nest Location ${location.name} Watchdog") } +def getRemDiagAppChildLabel() { return getChildName("NST Location ${location.name} Diagnostics") } +def getStorageAppChildLabel() { return getChildName("NST Location ${location.name} Storage") } def getChildName(str) { return "${str}${appDevName()}" } @@ -7538,7 +7974,11 @@ def getIssuePageUrl() { return "https://github.com/tonesto7/nest-manager/issues def slackMsgWebHookUrl() { return "https://hooks.slack.com/services/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" } def getAutoHelpPageUrl() { return "http://thingsthataresmart.wiki/index.php?title=NST_Manager#Nest_Automations" } def weatherApiKey() { return "b82aba1bb9a9d7f1" } -def getFirebaseAppUrl() { return "https://st-nest-manager.firebaseio.com" } +def getFbLegacyAppUrl() { return "https://st-nest-manager.firebaseio.com" } +def getFbMetricsUrl() { return atomicState?.appData?.settings?.database?.metricsUrl ?: "https://nst-manager-metrics.firebaseio.com" } +def getFbExceptionsUrl() { return atomicState?.appData?.settings?.database?.exceptionUrl ?: "https://nst-manager-exceptions.firebaseio.com" } +def getAppSettingsUrl() { return "https://raw.githubusercontent.com/${gitPath()}/Data/appConfig.json" } +def getAppSettingsFBUrl() { return "https://st-nest-manager.firebaseio.com/appSettings.json" } def getAppImg(imgName, on = null) { return (!disAppIcons || on) ? "https://raw.githubusercontent.com/tonesto7/nest-manager/${gitBranch()}/Images/App/$imgName" : "" } def getDevImg(imgName, on = null) { return (!disAppIcons || on) ? "https://raw.githubusercontent.com/tonesto7/nest-manager/${gitBranch()}/Images/Devices/$imgName" : "" } private Integer convertHexToInt(hex) { Integer.parseInt(hex,16) } @@ -7559,12 +7999,12 @@ def getStateSize() { return resultJson?.toString().length() //return state?.toString().length() } -def getStateSizePerc() { return (int) ((stateSize / 100000)*100).toDouble().round(0) } // +def getStateSizePerc() { return (int) ((stateSize / 100000)*100).toDouble().round(0) } -def debugStatus() { return !appDebug ? "Off" : "On" } -def deviceDebugStatus() { return !childDebug ? "Off" : "On" } -def isAppDebug() { return !appDebug ? false : true } -def isChildDebug() { return !childDebug ? false : true } +def debugStatus() { return !settings?.appDebug ? "Off" : "On" } +def deviceDebugStatus() { return !settings?.childDebug ? "Off" : "On" } +def isAppDebug() { return !settings?.appDebug ? false : true } +def isChildDebug() { return !settings?.childDebug ? false : true } def getLocationModes() { def result = [] @@ -7634,7 +8074,7 @@ def getObjType(obj, retType=false) { else { return "unknown"} } -def getShowHelp() { return atomicState?.showHelp == false ? false : true } +def getShowHelp() { return true } def getTimeZone() { def tz = null @@ -7653,19 +8093,35 @@ def formatDt(dt) { return tf.format(dt) } -def formatDt2(tm) { - def formatVal = settings?.useMilitaryTime ? "MMM d, yyyy - HH:mm:ss" : "MMM d, yyyy - h:mm:ss a" +def formatDt2(tm, fmt=null) { + def formatVal = fmt == null ? (settings?.useMilitaryTime ? "MMM d, yyyy - HH:mm:ss" : "MMM d, yyyy - h:mm:ss a") : fmt def tf = new SimpleDateFormat(formatVal) if(getTimeZone()) { tf.setTimeZone(getTimeZone()) } return tf.format(Date.parse("E MMM dd HH:mm:ss z yyyy", tm.toString())) } +private getTimeSeconds(timeKey, defVal, meth) { + def t0 = getTimestampVal(timeKey) + return !t0 ? defVal : GetTimeDiffSeconds(t0, null, meth).toInteger() +} + +void updTimestampMap(keyName, dt=null) { + def data = atomicState?.timestampDtMap ?: [:] + if(keyName) { data[keyName] = dt } + atomicState?.timestampDtMap = data +} + +def getTimestampVal(val) { + def tsData = atomicState?.timestampDtMap + if(val && tsData && tsData[val]) { return tsData[val] } + return null +} + def GetTimeDiffSeconds(strtDate, stpDate=null, methName=null) { //LogTrace("[GetTimeDiffSeconds] StartDate: $strtDate | StopDate: ${stpDate ?: "Not Sent"} | MethodName: ${methName ?: "Not Sent"})") if((strtDate && !stpDate) || (strtDate && stpDate)) { //if(strtDate?.contains("dtNow")) { return 10000 } - def now = new Date() - def stopVal = stpDate ? stpDate.toString() : formatDt(now) + def stopVal = stpDate ? stpDate.toString() : getDtNow() //formatDt(now) /* def startDt = Date.parse("E MMM dd HH:mm:ss z yyyy", strtDate) def stopDt = Date.parse("E MMM dd HH:mm:ss z yyyy", stopVal) @@ -7673,7 +8129,7 @@ def GetTimeDiffSeconds(strtDate, stpDate=null, methName=null) { */ def start = Date.parse("E MMM dd HH:mm:ss z yyyy", strtDate).getTime() def stop = Date.parse("E MMM dd HH:mm:ss z yyyy", stopVal).getTime() - def diff = (int) (long) (stop - start) / 1000 // + def diff = (int) (long) (stop - start) / 1000 LogTrace("[GetTimeDiffSeconds] Results for '$methName': ($diff seconds)") return diff } else { return null } @@ -7689,29 +8145,22 @@ def daysOk(days) { // parent only Method def notificationTimeOk() { -// try { - def strtTime = null - def stopTime = null - def now = new Date() - def sun = getSunriseAndSunset() // current based on geofence, previously was: def sun = getSunriseAndSunset(zipCode: zipCode) - if(settings?.qStartTime && settings?.qStopTime) { - if(settings?.qStartInput == "sunset") { strtTime = sun.sunset } - else if(settings?.qStartInput == "sunrise") { strtTime = sun.sunrise } - else if(settings?.qStartInput == "A specific time" && settings?.qStartTime) { strtTime = settings?.qStartTime } - - if(settings?.qStopInput == "sunset") { stopTime = sun.sunset } - else if(settings?.qStopInput == "sunrise") { stopTime = sun.sunrise } - else if(settings?.qStopInput == "A specific time" && settings?.qStopTime) { stopTime = settings?.qStopTime } - } else { return true } - if(strtTime && stopTime) { - return timeOfDayIsBetween(strtTime, stopTime, new Date(), getTimeZone()) ? false : true - } else { return true } -/* - } catch (ex) { - log.error "notificationTimeOk Exception:", ex - sendExceptionData(ex, "notificationTimeOk") - } -*/ + def strtTime = null + def stopTime = null + def now = new Date() + def sun = getSunriseAndSunset() // current based on geofence, previously was: def sun = getSunriseAndSunset(zipCode: zipCode) + if(settings?.qStartTime && settings?.qStopTime) { + if(settings?.qStartInput == "sunset") { strtTime = sun.sunset } + else if(settings?.qStartInput == "sunrise") { strtTime = sun.sunrise } + else if(settings?.qStartInput == "A specific time" && settings?.qStartTime) { strtTime = settings?.qStartTime } + + if(settings?.qStopInput == "sunset") { stopTime = sun.sunset } + else if(settings?.qStopInput == "sunrise") { stopTime = sun.sunrise } + else if(settings?.qStopInput == "A specific time" && settings?.qStopTime) { stopTime = settings?.qStopTime } + } else { return true } + if(strtTime && stopTime) { + return timeOfDayIsBetween(strtTime, stopTime, new Date(), getTimeZone()) ? false : true + } else { return true } } def time2Str(time) { @@ -7725,7 +8174,7 @@ def time2Str(time) { def epochToTime(tm) { def tf = new SimpleDateFormat("h:mm a") - tf?.setTimeZone(getTimeZone()) + tf.setTimeZone(getTimeZone()) return tf.format(tm) } @@ -7763,7 +8212,7 @@ def notifValEnum(allowCust = false) { def pollValEnum(device=false) { def vals = [:] - if(device && inReview()) { vals = [ 30:"30 Seconds" ] } + // if(device && inReview()) { vals = [ 30:"30 Seconds" ] } vals << [ 60:"1 Minute", 120:"2 Minutes", 180:"3 Minutes", 240:"4 Minutes", 300:"5 Minutes", 600:"10 Minutes", 900:"15 Minutes", 1200:"20 Minutes", 1500:"25 Minutes", @@ -7797,7 +8246,7 @@ def strCapitalize(str) { def getInputEnumLabel(inputName, enumName) { def result = "Not Set" - if(input && enumName) { + if(inputName && enumName) { enumName.each { item -> if(item?.key.toString() == inputName?.toString()) { result = item?.value @@ -7822,28 +8271,15 @@ def minDevVer2Str(val) { } } -/* -def b64Action(String str, dec=false) { - if (str) { - if(dec) { - return (String) str?.bytes?.decodeBase64() - } else { - return (String) str?.bytes?.encodeBase64(true) - } - } -} -*/ - /****************************************************************************** -* DIAGNOSTIC & NEST API INFO PAGES * +* DIAGNOSTIC & NEST API INFO PAGES * *******************************************************************************/ -def alarmTestPage () { +def alarmTestPage() { def execTime = now() dynamicPage(name: "alarmTestPage", install: false, uninstall: false) { if(atomicState?.protects) { section("Select Carbon/Smoke Device to Test:") { - input(name: "alarmCoTestDevice", title:"Select the Protect to Test", type: "enum", required: false, multiple: false, submitOnChange: true, - metadata: [values:atomicState?.protects], image: getAppImg("protect_icon.png")) + input name: "alarmCoTestDevice", title:"Select the Protect to Test", type: "enum", required: false, multiple: false, submitOnChange: true, metadata: [values:atomicState?.protects], image: getAppImg("protect_icon.png") } if(settings?.alarmCoTestDevice) { section("Select the Event to Generate:") { @@ -7882,16 +8318,16 @@ def alarmTestPage () { } } } + devPageFooter("protTestLoadCnt", execTime) } - devPageFooter("protTestLoadCnt", execTime) } void resetAlarmTest() { LogAction("Resetting Protect Alarm Test back to the default.", "info", true) - settingUpdate("alarmCoTestDevice", "") - settingUpdate("alarmCoTestDeviceSimSmoke", "false") - settingUpdate("alarmCoTestDeviceSimCo", "false") - settingUpdate("alarmCoTestDeviceSimLowBatt", "false") + settingRemove("alarmCoTestDevice") + settingRemove("alarmCoTestDeviceSimSmoke") + settingRemove("alarmCoTestDeviceSimCo") + settingRemove("alarmCoTestDeviceSimLowBatt") atomicState?.isAlarmCoTestActive = false atomicState?.curProtTestPageData = null } @@ -8044,52 +8480,66 @@ def sendFeedbackPage() { } } -def createManagerBackupDataJson() { - def noShow = ["authToken", "accessToken", "curAlerts", "curAstronomy", "curForecast", "curWeather"] - def sData = getSettings()?.sort()?.findAll { !(it.key in noShow) } - def setData = [:] - sData?.sort().each { item -> - setData[item?.key] = item?.value - } - def stData = getState()?.sort()?.findAll { !(it.key in noShow) } - def stateData = [:] - stData?.sort().each { item -> - stateData[item?.key] = item?.value +def procDiagCmd() { + def status = [:] + def rData = request?.JSON + // log.trace "procDiagCmd($rData)" + if(rData) { + status["code"] = 200 + if(rData?.cmd) { + switch(rData?.cmd) { + case "stateCleanup": + LogAction("Web Diagnostic Command (${rData?.cmd} received... Running stateCleanup() in 3 seconds", "debug", true) + runIn(3, "stateCleanup", [overwrite: true]) + break + case "runUpdated": + LogAction("Web Diagnostic Command (${rData?.cmd} received... Running update() Method in 3 seconds", "debug", true) + runIn(3, "updated", [overwrite: true]) + break + case "sendFirebaseData": + LogAction("Web Diagnostic Command (${rData?.cmd} received... Running sendInstallData() Method in 3 seconds", "debug", true) + runIn(3, "sendInstallData", [overwrite: true]) + break + } + } } - def result = ["settingsData":setData, "stateData":stateData, "backupDt":getDtNow().toString()] - def resultJson = new groovy.json.JsonOutput().toJson(result) - return resultJson + return [contentType: 'application/json', gotData: (rData != null), status: status?.code] } def getDeviceMetricCnts() { def data = [:] def devs = app.getChildDevices(true) if(devs?.size() >= 1) { - devs?.each { dev -> - def mData = dev?.getMetricCntData() - if(mData != null) { - //log.debug "mData: ${mData}" - mData?.each { md -> - def objKey = md?.key.toString() - def objVal = md?.value?.toInteger() ?: 0 - if(data?.containsKey("${objKey}")) { - def newVal = 0 - def prevVal = data?.get("${objKey}") ?: 0 - newVal = prevVal?.toInteger()+objVal - //log.debug "$objKey Data: [prevVal: $prevVal | objVal: $objVal | newVal: $newVal]" - data << ["${objKey}":newVal] - } else { - data << ["${objKey}":objVal] + try { + devs?.each { dev -> + def mData = dev?.getMetricCntData() + if(mData != null) { + //log.debug "mData: ${mData}" + mData?.each { md -> + def objKey = md?.key.toString() + def objVal = md?.value?.toInteger() ?: 0 + if(data?.containsKey("${objKey}")) { + def newVal = 0 + def prevVal = data?.get("${objKey}") ?: 0 + newVal = prevVal?.toInteger()+objVal + //log.debug "$objKey Data: [prevVal: $prevVal | objVal: $objVal | newVal: $newVal]" + data << ["${objKey}":newVal] + } else { + data << ["${objKey}":objVal] + } } } } + } catch (ex) { + log.error "getDeviceMetricCnts", ex + sendExceptionData(ex, "getDeviceMetricCnts") } } //log.debug "data: ${data}" return data } /****************************************************************************** -* Firebase Analytics Functions * +* Firebase Analytics Functions * *******************************************************************************/ def createInstallDataJson(returnMap=false) { try { @@ -8132,15 +8582,15 @@ def createInstallDataJson(returnMap=false) { if(settings?.optInAppAnalytics || settings?.optInAppAnalytics == null) { data = [ "guid":atomicState?.installationId, "beta":betaMarker(), "versions":versions, "thermostats":tstatCnt, "protects":protCnt, "vthermostats":vstatCnt, "cameras":camCnt, "appErrorCnt":appErrCnt, "devErrorCnt":devErrCnt, - "installDt": atomicState?.installData?.dt, "updatedDt": atomicState?.installData?.updatedDt, "automations":automations, "timeZone":tz, "apiCmdCnt":apiCmdCnt, "apiStrReqCnt":apiStrReqCnt, - "apiDevReqCnt":apiDevReqCnt, "apiMetaReqCnt":apiMetaReqCnt, "appNotifSentCnt":appNotifSentCnt, "apiRestStrEvtCnt":apiRestStrEvtCnt, "appUseMetCnt":appUseMetCnt, "devUseMetCnt":devUseMetCnt, - "stateUsage":"${getStateSizePerc()}%", "mobileClient":cltType, "datetime":getDtNow()?.toString(), "optOut":false + "installDt": atomicState?.installData?.dt, "updatedDt": atomicState?.installData?.updatedDt, "automations":automations, "timeZone":tz, "apiCmdCnt":apiCmdCnt, "apiStrReqCnt":apiStrReqCnt, "apiDevReqCnt":apiDevReqCnt, + "apiMetaReqCnt":apiMetaReqCnt, "appNotifSentCnt":appNotifSentCnt, "apiRestStrEvtCnt":apiRestStrEvtCnt, "appUseMetCnt":appUseMetCnt, "devUseMetCnt":devUseMetCnt,"stateUsage":"${getStateSizePerc()}%", "mobileClient":cltType, + "liteAppMode": isAppLiteMode(), "datetime":getDtNow()?.toString(), "optOut":false ] } else { data = [ "guid":atomicState?.installationId, "beta":betaMarker(), "versions":versions, "thermostats":tstatCnt, "protects":protCnt, "vthermostats":vstatCnt, "cameras":camCnt, "appErrorCnt":appErrCnt, "devErrorCnt":devErrCnt, - "apiStrReqCnt":apiStrReqCnt, "apiDevReqCnt":apiDevReqCnt, "apiMetaReqCnt":apiMetaReqCnt, "installDt": atomicState?.installData?.dt, "updatedDt": atomicState?.installData?.updatedDt, - "automations":automations, "timeZone":tz, "apiCmdCnt":apiCmdCnt, "apiRestStrEvtCnt":apiRestStrEvtCnt, "stateUsage":"${getStateSizePerc()}%", "datetime":getDtNow()?.toString(), "optOut":true + "apiStrReqCnt":apiStrReqCnt, "apiDevReqCnt":apiDevReqCnt, "apiMetaReqCnt":apiMetaReqCnt, "installDt": atomicState?.installData?.dt, "updatedDt": atomicState?.installData?.updatedDt,"automations":automations, + "liteAppMode": isAppLiteMode(), "timeZone":tz, "apiCmdCnt":apiCmdCnt, "apiRestStrEvtCnt":apiRestStrEvtCnt, "stateUsage":"${getStateSizePerc()}%", "datetime":getDtNow()?.toString(), "optOut":true ] } if(returnMap == true) { @@ -8207,13 +8657,52 @@ def getStateData() { def lastCmdDesc() { def cmdDesc = "" def map = [:] - map["DateTime"] = atomicState?.lastCmdSentDt ?: "Nothing found" + map["DateTime"] = getTimestampVal("lastCmdSentDt") ?: "Nothing found" map["Cmd Sent"] = atomicState?.lastCmdSent ?: "Nothing found" map["Cmd Result"] = atomicState?.lastCmdSentStatus ? "(${atomicState?.lastCmdSentStatus})" : "(Nothing found)" cmdDesc += getMapDescStr(map) return cmdDesc } +def getWebHeaderHtml(title, clipboard=true, vex=false, swiper=false, charts=false) { + def html = """ + + + + + + + + + + NST Diagnostics (${atomicState?.structName}) - ${title} + + + + + + + + + + + + """ + html += clipboard ? """""" : "" + html += vex ? """""" : "" + html += swiper ? """""" : "" + html += vex ? """""" : "" + html += vex ? """""" : "" + html += swiper ? """""" : "" + html += charts ? """""" : "" + html += vex ? """""" : "" + + return html +} + def renderDiagHome() { try { def remDiagUrl = getAppEndpointUrl("diagHome") @@ -8223,6 +8712,11 @@ def renderDiagHome() { def deviceUrl = getAppEndpointUrl("getDeviceData") def appDataUrl = getAppEndpointUrl("getAppData") def instDataUrl = getAppEndpointUrl("getInstData") + def devTilesUrl = getAppEndpointUrl("deviceTiles") + def tstatTilesUrl = getAppEndpointUrl("tstatTiles") + def protTilesUrl = getAppEndpointUrl("protectTiles") + def camTilesUrl = getAppEndpointUrl("cameraTiles") + def weatherTilesUrl = getAppEndpointUrl("weatherTile") def sPerc = getStateSizePerc() ?: 0 def instData = atomicState?.installData def cmdDesc = lastCmdDesc().toString().replaceAll("\n", "
") @@ -8230,31 +8724,15 @@ def renderDiagHome() { //log.debug "newHtml: $newHtml" def html = """ - - - - - - NST Diagnostics ${atomicState?.structName} - - - - - - - - - - + ${getWebHeaderHtml("Location")} - - + - +
@@ -8263,7 +8741,7 @@ def renderDiagHome() {
-

Diagnostics Home (${atomicState?.structName})

+

Diagnostics Home

@@ -8275,9 +8753,8 @@ def renderDiagHome() {
- - -
+ +
@@ -8285,7 +8762,7 @@ def renderDiagHome() {

Install Details:

-
+
@@ -8303,12 +8780,7 @@ def renderDiagHome() {
Install ID:
${atomicState?.installationId}
-
- Token Num:
${atomicState?.authTokenNum ?: "Not Found"}
-
-
- API Token Ver:
${atomicState?.metaData?.client_version}
-
+
Install Date:
${instData?.dt}
@@ -8336,7 +8808,7 @@ def renderDiagHome() {
-
+

Last Command Info:

@@ -8352,11 +8824,11 @@ def renderDiagHome() {
-
-
+
+

Shortcuts

-
-
+
+

View Logs

Manager Data

@@ -8368,20 +8840,51 @@ def renderDiagHome() {

AppData File

-
+
+ +
+
+

Diagnostic Commands

+
+ +
+ +
+
+

Device Tiles

+
+
+
+

All Devices

+ ${atomicState?.thermostats ? """

Thermostat Devices

""" : ""} + ${atomicState?.protects ? """

Protect Devices

""" : ""} +
+
+ ${atomicState?.cameras ? """

Camera Devices

""" : ""} + ${atomicState?.weatherDevice ? """

Weather Device

""" : ""} +
+
+
-
+
External Access URL:
-
+
-
- +
+ """ +/* """ */ render contentType: "text/html", data: html } catch (ex) { log.error "renderDiagUrl Exception:", ex } } @@ -8502,36 +9005,31 @@ def renderManagerData() { def metaDesc = getMapDescStr(getMetadata()) def html = """ - - - - - - - - - - NST Diagnostics ${atomicState?.structName} - Manager Data - - - - - - - - - - - - - - - + ${getWebHeaderHtml("Manager Data")} + - +
-

Manager Data ${atomicState?.structName}

+

Manager Data

-
+
-
+
@@ -8586,48 +9084,58 @@ def renderManagerData() {
-
- -
-
+
+
+

Setting Data:

-
-
+
+
${setDesc.toString().replaceAll("\n", "
")}
-
-
+
+
-
-
+
+

State Data:

-
-
+
+
${stateDesc.toString().replaceAll("\n", "
")}
-
-
+
+
-
-
+
+

Meta Data:

-
-
+
+
${metaDesc.toString().replaceAll("\n", "
")}
-
-
- +
+
-
+
-
-
+
+
- - + + """ @@ -8653,76 +9161,52 @@ def renderAutomationData() { def metaDesc = getMapDescStr(cApp?.getMetadata()) appHtml += """
-
+

${cApp?.getLabel()}:

-
-
+
+
-
-
+
+

Setting Data:

-
-
+
+
${setDesc.toString().replaceAll("\n", "
")}
-
+
-
-
+
+

State Data:

-
-
+
+
${stateDesc.toString().replaceAll("\n", "
")}
-
-
+
+
-
-
+
+

Meta Data:

-
-
+
+
${metaDesc.toString().replaceAll("\n", "
")}
-
-
+
+
-
+
""" appNum = appNum+1 } def html = """ - - - - - - - - - - NST Diagnostics ${atomicState?.structName} - Automation Data - - - - - - - - - - - - - - - + ${getWebHeaderHtml("Automation Data")} + - +
-

Automation Data ${atomicState?.structName}

+

Automation Data

@@ -8761,21 +9245,34 @@ def renderAutomationData() {
-
+
${appHtml}
-
- - + + """ + /* """ */ render contentType: "text/html", data: html } catch (ex) { log.error "renderAutomationData Exception:", ex } } @@ -8844,58 +9341,57 @@ def renderDeviceData() { commDesc += "${cnt>1 ? "\n\n" : "\n"} • ${cmd.name}(${!cmd?.arguments ? "" : cmd?.arguments.toString().toLowerCase().replaceAll("\\[|\\]", "")})" cnt = cnt+1 } - def data = dev?.capabilities?.sort()?.collect {it as String} def t0 = [ "capabilities":data ] def capDesc = getMapDescStr(t0) devHtml += """
-

${dev?.getLabel()}:

+

${dev?.getLabel()}:

-
-
+
+

Setting Data:

-
-
+
+
${setDesc.toString().replaceAll("\n", "
")}
-
-
-
-
+
+
+
+

State Data:

-
-
+
+
${stateDesc.toString().replaceAll("\n", "
")}
-
-
-
-
+
+
+
+

Attribute Data:

-
-
+
+
${attrDesc.toString().replaceAll("\n", "
")}
-
-
-
-
-

Command Data:

+
+
+
+
+

Command Data:

-
${commDesc.toString().replaceAll("\n", "
")}
+
${commDesc.toString().replaceAll("\n", "
")}
-
+
-

Capability Data:

+

Capability Data:

-
${capDesc.toString().replaceAll("\n", "
")}
+
${capDesc.toString().replaceAll("\n", "
")}
-
+
""" @@ -8903,37 +9399,17 @@ def renderDeviceData() { } def html = """ - - - - - - - - - - NST Diagnostics ${atomicState?.structName} - Automation Data - - - - - - - - - - - - - - - + ${getWebHeaderHtml("Device Data", true, true, true, true)} + - +
-

Device Data ${atomicState?.structName}

+

Device Data

@@ -8972,21 +9448,165 @@ def renderDeviceData() {
-
+
${devHtml}
- - + + + + """ + /* """ */ + log.debug apiServerUrl("/api/rooms") + render contentType: "text/html", data: html + } catch (ex) { log.error "renderDeviceData Exception:", ex } +} + +def getTstatTiles() { + return renderDeviceTiles("Nest Thermostat") +} + +def getProtectTiles() { + return renderDeviceTiles("Nest Protect") +} + +def getCamTiles() { + return renderDeviceTiles("Nest Camera") +} + +def getWeatherTile() { + return renderDeviceTiles("Nest Weather") +} + +def renderDeviceTiles(type=null) { + try { + def devHtml = "" + def navHtml = "" + def scrStr = "" + def devices = app.getChildDevices(true) + def devNum = 1 + devices?.sort {it?.getLabel()}.each { dev -> + def navMap = [:] + def hasHtml = (dev?.hasHtml() == true) + if((hasHtml && !type) || (hasHtml && type && dev?.name == type)) { + navMap = ["key":dev?.getLabel(), "items":[]] + def navItems = navHtmlBuilder(navMap, devNum) + if(navItems?.html) { navHtml += navItems?.html } + if(navItems?.js) { scrStr += navItems?.js } + devHtml += """ +
+
+

${dev?.getLabel()}: (v${dev?.devVer()})

+
+
+
+
${dev?.getDeviceTile(devNum)}
+
+
+
+ """ + } + devNum = devNum+1 + } + + def html = """ + + ${getWebHeaderHtml(type, true, true, true, true)} + + + + + + + +
+ + +
+ + +
+
+
+ ${devHtml} +
+
+
+
+ + + + \$("#goHomeBtn").click(function() { + closeNavMenu(); + toggleMenuBtn(); + window.location.replace('${getAppEndpointUrl("diagHome")}'); + }); + """ +/* """ */ render contentType: "text/html", data: html } catch (ex) { log.error "renderDeviceData Exception:", ex } } @@ -9004,31 +9624,8 @@ def renderHtmlMapDesc(title, heading, datamap) { def navHtml = "" def html = """ - - - - - - - - - - NST Diagnostics ${atomicState?.structName} - ${title} - - - - - - - - - - - - - - - + ${getWebHeaderHtml(title)} + @@ -9062,7 +9659,7 @@ def renderHtmlMapDesc(title, heading, datamap) {
-

${heading}

+

${heading}

@@ -9072,34 +9669,43 @@ def renderHtmlMapDesc(title, heading, datamap) {
-
+
-
+

${heading}:

-
-
+
+
${datamap.toString().replaceAll("\n", "
")}
-
+
- + + """ - /* "" */ + /* """ */ render contentType: "text/html", data: html } catch (ex) { log.error "getAppDataFile Exception:", ex } } def sendInstallData() { - sendFirebaseData(createInstallDataJson(), "installData/clients/${atomicState?.installationId}.json", null, "heartbeat") + if(atomicState?.cltMetBlacklisted) { + LogAction("Metrics Upload has been BLACKLISTED for this client.", "warn", true) + } else { sendFirebaseData(getFbMetricsUrl(), createInstallDataJson(), "clients/${atomicState?.installationId}.json", null, "heartbeat") } } def removeInstallData() { - return removeFirebaseData("installData/clients/${atomicState?.installationId}.json") + return removeFirebaseData("clients/${atomicState?.installationId}.json") } def sendInstallSlackNotif(inst=true) { @@ -9116,10 +9722,10 @@ def sendInstallSlackNotif(inst=true) { str += "\n • App Version: v${appVersion()}" str += "\n • Mobile Client: ${cltType}" str += atomicState?.authToken && atomicState?.authTokenNum ? "\n • TokenNum: ${atomicState?.authTokenNum}" : "" - str += atomicState?.authToken && atomicState?.authTokenCreatedDt ? "\n • TokenCreated: ${atomicState?.authTokenCreatedDt}" : "" + str += atomicState?.authToken && getTimestampVal("authTokenCreatedDt") ? "\n • TokenCreated: ${getTimestampVal("authTokenCreatedDt")}" : "" def tf = new SimpleDateFormat("M/d/yyyy - h:mm a") if(getTimeZone()) { tf.setTimeZone(getTimeZone()) } - str += atomicState?.authToken && atomicState?.authTokenExpires ? "\n • TokenExpires: ${tf?.format(atomicState?.authTokenExpires)}" : "" + str += atomicState?.authToken && atomicState?.authTokenExpires ? "\n • TokenExpires: ${tf.format(atomicState?.authTokenExpires)}" : "" def res = [:] res << ["username":"New User Notification"] res << ["icon_emoji":":spock-hand:"] @@ -9133,7 +9739,23 @@ def sendInstallSlackNotif(inst=true) { sendDataToSlack(json, "", "post", "${typeStr} Slack Notif") } -def getDbExceptPath() { return atomicState?.appData?.database?.newexceptionPath ?: "newexceptionData" } +def getDbExceptPath() { return atomicState?.appData?.settings?.database?.exceptionKey ?: "exceptions" } + +def ok2SendException(ex) { + def retVal = true + if(allowDbException() != true) { + retVal = false + // Nothing to see here! + } else if(atomicState?.cltExcBlacklisted) { + LogAction("Exception Data Upload has been BLACKLISTED for this client.", "warn", true) + retVal = false + } else if(!(settings?.optInSendExceptions || settings?.optInSendExceptions == null)) { + retVal = false + } else if (ex instanceof java.util.concurrent.TimeoutException) { + retVal = false + } + return retVal +} def sendExceptionData(ex, methodName, isChild = false, autoType = null) { try { @@ -9141,41 +9763,43 @@ def sendExceptionData(ex, methodName, isChild = false, autoType = null) { def labelstr = (settings?.debugAppendAppName || settings?.debugAppendAppName == null) ? "${app.label} | " : "" //LogAction("${labelstr}sendExceptionData(method: $methodName, isChild: $isChild, autoType: $autoType)", "info", false) LogAction("${labelstr}sendExceptionData(method: $methodName, isChild: $isChild, autoType: $autoType, ex: ${ex})", "error", showErrLog) - if(atomicState?.appData?.database?.disableExceptions == true) { - return - } else { - def exCnt = atomicState?.appExceptionCnt ?: 1 - atomicState?.appExceptionCnt = exCnt?.toInteger() + 1 + def exCnt = atomicState?.appExceptionCnt ?: 1 + atomicState?.appExceptionCnt = exCnt?.toInteger() + 1 + if(ok2SendException(ex)) { def exString = "${ex}" - if(settings?.optInSendExceptions || settings?.optInSendExceptions == null) { - generateInstallId() - def appType = isChild && autoType ? "automationApp/${autoType}" : "managerApp" - def exData =[:] - if(isChild) { - exData = ["methodName":methodName, "automationType":autoType, "appVersion":(appVersion() ?: "Not Available"),"errorMsg":exString, "errorDt":getDtNow().toString()] - } else { - exData = ["methodName":methodName, "appVersion":(appVersion() ?: "Not Available"),"errorMsg":exString, "errorDt":getDtNow().toString()] - } - def results = new groovy.json.JsonOutput().toJson(exData) - sendFirebaseData(results, "${getDbExceptPath()}/${appType}/${methodName}/${atomicState?.installationId}.json", "post", "Exception") + generateInstallId() + def appType = isChild && autoType ? "automationApp/${autoType}" : "managerApp" + def exData =[:] + if(isChild) { + exData = ["methodName":methodName, "automationType":autoType, "appVersion":(appVersion() ?: "Not Available"),"errorMsg":exString, "errorDt":getDtNow().toString()] + } else { + exData = ["methodName":methodName, "appVersion":(appVersion() ?: "Not Available"),"errorMsg":exString, "errorDt":getDtNow().toString()] } + def results = new groovy.json.JsonOutput().toJson(exData) + sendFirebaseData(getFbExceptionsUrl(), results, "${getDbExceptPath()}/${appType}/${methodName}/${atomicState?.installationId}.json", "post", "Exception") + } + if(ex instanceof physicalgraph.exception.StateCharacterLimitExceededException) { + state.remove("remDiagLogDataStore") + settingUpdate("resetAllData", "true", "bool") + atomicState?.resetAllData = false + runIn(20, "updated", [overwrite: true]) } } catch (e) { - log.debug "other exception caught" + log.debug "sendExceptionData: other exception caught" } } def sendChildExceptionData(devType, devVer, ex, methodName) { def showErrLog = (atomicState?.enRemDiagLogging && settings?.enRemDiagLogging) ? true : false - def exString = "${ex}" LogAction("sendChildExceptionData(device: $deviceType, devVer: $devVer, method: $methodName, ex: ${ex}", "error", showErrLog) def exCnt = atomicState?.childExceptionCnt ?: 1 atomicState?.childExceptionCnt = exCnt.toInteger() + 1 - if(settings?.optInSendExceptions || settings?.optInSendExceptions == null) { + if(ok2SendException(ex)) { generateInstallId() + def exString = "${ex}" def exData = ["deviceType":devType, "devVersion":(devVer ?: "Not Available"), "methodName":methodName, "errorMsg":exString, "errorDt":getDtNow().toString()] def results = new groovy.json.JsonOutput().toJson(exData) - sendFirebaseData(results, "${getDbExceptPath()}/${devType}/${methodName}/${atomicState?.installationId}.json", "post", "Exception") + sendFirebaseData(getFbExceptionsUrl(), results, "${getDbExceptPath()}/${devType}/${methodName}/${atomicState?.installationId}.json", "post", "Exception") } } @@ -9183,33 +9807,23 @@ def sendFeedbackData(msg) { def cltId = atomicState?.installationId def exData = ["guid":atomicState?.installationId, "version":appVersion(), "feedbackMsg":(msg ? msg : (settings?.feedbackMsg ?: "No Text")), "msgDt":getDtNow().toString()] def results = new groovy.json.JsonOutput().toJson(exData) - if(sendFirebaseData(results, "feedback/data.json", "post", "Feedback")) { + if(sendFirebaseData(getFbLegacyAppUrl(), results, "feedback/data.json", "post", "Feedback")) { atomicState?.feedbackPending = false if(!msg) { atomicState?.lastFeedbackData = ["lastMsg":settings?.feedbackMsg, "lastMsgDt":getDtNow().toString(), "lastAppVer":appVersion()] } } } -def sendFirebaseData(data, pathVal, cmdType=null, type=null, noAsync=false) { +def sendFirebaseData(url, data, pathVal, cmdType=null, type=null) { + LogAction("sendFirebaseData(${data}, ${pathVal}, $cmdType, $type", "info", true) LogTrace("sendFirebaseData(${data}, ${pathVal}, $cmdType, $type") - - def allowAsync = false - def metstr = "sync" - if(atomicState?.appData && atomicState?.appData?.pollMethod?.allowAsync) { - allowAsync = true - metstr = "async" - } - if(allowAsync && !noAsync) { - return queueFirebaseData(data, pathVal, cmdType, type) - } else { - return syncSendFirebaseData(data, pathVal, cmdType, type) - } + return queueFirebaseData(url, data, pathVal, cmdType, type) } -def queueFirebaseData(data, pathVal, cmdType=null, type=null) { +def queueFirebaseData(url, data, pathVal, cmdType=null, type=null) { LogTrace("queueFirebaseData(${data}, ${pathVal}, $cmdType, $type") def result = false def json = new groovy.json.JsonOutput().prettyPrint(data) - def params = [ uri: "${getFirebaseAppUrl()}/${pathVal}", body: json.toString() ] + def params = [ uri: "${url}/${pathVal}", body: json.toString() ] def typeDesc = type ? "${type}" : "Data" try { if(!cmdType || cmdType == "put") { @@ -9222,7 +9836,7 @@ def queueFirebaseData(data, pathVal, cmdType=null, type=null) { } catch(ex) { log.error "queueFirebaseData (type: $typeDesc) Exception:", ex - sendExceptionData(ex, "queueFirebaseData") + //sendExceptionData(ex, "queueFirebaseData") } return result } @@ -9237,7 +9851,7 @@ def processFirebaseSlackResponse(resp, data) { if(typeDesc?.toString() == "Remote Diag Logs") { } else { - if(typeDesc?.toString() == "heartbeat") { atomicState?.lastAnalyticUpdDt = getDtNow() } + if(typeDesc?.toString() == "heartbeat") { updTimestampMap("lastAnalyticUpdDt", getDtNow()) } } result = true } @@ -9248,7 +9862,7 @@ def processFirebaseSlackResponse(resp, data) { LogAction("processFirebaseSlackResponse: 'Unexpected' Response: ${resp?.status}", "warn", true) } if(resp?.hasError()) { - LogAction("processFirebaseSlackResponse: errorData: $resp.errorData errorMessage: $resp.errorMessage", "error", true) + LogAction("processFirebaseSlackResponse: errorData: $resp.errorData errorMessage: $resp.errorMessage", "error", true) } } catch(ex) { log.error "processFirebaseSlackResponse (type: $typeDesc) Exception:", ex @@ -9256,52 +9870,6 @@ def processFirebaseSlackResponse(resp, data) { } } -def syncSendFirebaseData(data, pathVal, cmdType=null, type=null) { - LogTrace("syncSendFirebaseData(${data}, ${pathVal}, $cmdType, $type") - def result = false - def json = new groovy.json.JsonOutput().prettyPrint(data) - def params = [ uri: "${getFirebaseAppUrl()}/${pathVal}", body: json.toString() ] - def typeDesc = type ? "${type}" : "Data" - def respData - try { - if(!cmdType || cmdType == "put") { - httpPutJson(params) { resp -> - respData = resp - } - } else if (cmdType == "post") { - httpPostJson(params) { resp -> - respData = resp - } - } - if(respData) { - //log.debug "respData: ${respData}" - if(respData?.status == 200) { - LogAction("sendFirebaseData: ${typeDesc} Data Sent SUCCESSFULLY", "info", false) - if(typeDesc.toString() == "Remote Diag Logs") { - - } else { - if(typeDesc?.toString() == "heartbeat") { atomicState?.lastAnalyticUpdDt = getDtNow() } - } - result = true - } - else if(respData?.status == 400) { - LogAction("sendFirebaseData: 'Bad Request': ${respData?.status}", "error", true) - } - else { - LogAction("sendFirebaseData: 'Unexpected' Response: ${respData?.status}", "warn", true) - } - } - } - catch (ex) { - if(ex instanceof groovyx.net.http.HttpResponseException) { - LogAction("sendFirebaseData: 'HttpResponseException': ${ex?.message}", "error", true) - } - else { log.error "sendFirebaseData: ([$data, $pathVal, $cmdType, $type]) Exception:", ex } - sendExceptionData(ex, "sendFirebaseData") - } - return result -} - def sendDataToSlack(data, pathVal, cmdType=null, type=null) { LogAction("sendDataToSlack(${data}, ${pathVal}, $cmdType, $type", "trace", false) def result = false @@ -9313,27 +9881,7 @@ def sendDataToSlack(data, pathVal, cmdType=null, type=null) { if(!cmdType || cmdType == "post") { asynchttp_v1.post(processFirebaseSlackResponse, params, [ type: "${typeDesc}"]) result = true -/* - httpPostJson(params) { resp -> - respData = resp - } -*/ - } -/* - if(respData) { - //log.debug "respData: ${respData}" - if(respData?.status == 200) { - LogAction("sendDataToSlack: ${typeDesc} Data Sent SUCCESSFULLY", "info", false) - result = true - } - else if(respData?.status == 400) { - LogAction("sendDataToSlack: 'Bad Request': ${respData?.status}", "error", true) - } - else { - LogAction("sendDataToSlack: 'Unexpected' Response: ${respData?.status}", "warn", true) - } } -*/ } catch (ex) { if(ex instanceof groovyx.net.http.HttpResponseException) { @@ -9349,8 +9897,11 @@ def removeFirebaseData(pathVal) { LogAction("removeFirebaseData(${pathVal})", "trace", false) def result = true try { - httpDelete(uri: "${getFirebaseAppUrl()}/${pathVal}") { resp -> - LogAction("resp: ${resp?.status}", "info", true) + httpDelete(uri: "${getFbMetricsUrl()}/${pathVal}") { resp -> + LogAction("cur FB resp: ${resp?.status}", "info", true) + } + httpDelete(uri: "${getFbLegacyAppUrl()}/installData/${pathVal}") { resp -> + LogAction("old FB resp: ${resp?.status}", "info", true) } } catch (ex) { @@ -9374,22 +9925,14 @@ def removeFirebaseData(pathVal) { // Calls by Automation children // parent only method -def automationNestModeEnabled(val=null) { - LogTrace("automationNestModeEnabled: val: $val") - if(val == null) { - return atomicState?.automationNestModeEnabled ?: false - } else { - atomicState.automationNestModeEnabled = val.toBoolean() - } - return atomicState?.automationNestModeEnabled ?: false -} def remSenLock(val, myId) { def res = false + def k = "remSenLock${val}" if(val && myId && !parent) { - def lval = atomicState?."remSenLock${val}" + def lval = atomicState?."${k}" if(!lval) { - atomicState?."remSenLock${val}" = myId + atomicState?."${k}" = myId res = true } else if(lval == myId) { res = true } } @@ -9399,11 +9942,12 @@ def remSenLock(val, myId) { def remSenUnlock(val, myId) { def res = false if(val && myId && !parent) { - def lval = atomicState?."remSenLock${val}" + def k = "remSenLock${val}" + def lval = atomicState?."${k}" if(lval) { if(lval == myId) { - atomicState?."remSenLock${val}" = null - state.remove("remSenLock${val}" as String) + atomicState?."${k}" = null + state.remove("${k}" as String) res = true } } else { res = true } @@ -9411,8 +9955,26 @@ def remSenUnlock(val, myId) { return res } +def automationNestModeEnabled(val=null) { + LogTrace("automationNestModeEnabled: $val") + return getSetVal("automationNestModeEnabled", val) +/* + if(val == null) { + return atomicState?.automationNestModeEnabled ?: false + } else { + atomicState.automationNestModeEnabled = val.toBoolean() + } + return atomicState?.automationNestModeEnabled ?: false +*/ +} + def setNModeActive(val=null) { - LogTrace("setNModeActive: val: $val") + LogTrace("setNModeActive: $val") + def myKey = "automationNestModeEcoActive" + def retVal + if(!automationNestModeEnabled(null)) { + retVal = getSetVal(myKey, false) +/* if(automationNestModeEnabled(null)) { if(val == null) { return atomicState?.automationNestModeEcoActive ?: false @@ -9421,6 +9983,18 @@ def setNModeActive(val=null) { } } else { atomicState.automationNestModeEcoActive = false } return atomicState?.automationNestModeEcoActive ?: false +*/ + } else { retVal = getSetVal(myKey, val) } + return retVal +} + +def getSetVal(k, val=null) { + if(val == null) { + return atomicState?."${k}" ?: false + } else { + atomicState."${k}" = val.toBoolean() + } + return atomicState?."${k}" ?: false } // Most of this is obsolete after upgrade to V5 is complete @@ -9460,7 +10034,6 @@ def initAutoApp() { def uninstAutomationApp() { LogTrace("uninstAutomationApp") def autoType = getAutoType() - //def migrate = parent?.migrationInProgress() if(autoType == "schMot") { def myID = getMyLockId() //if(schMotTstat && myID && parent && !migrate) { @@ -9533,29 +10106,6 @@ def getAutoType() { return !parent ? "" : atomicState?.automationType } def getAutoIcon(type) { if(type) { switch(type) { -/* - case "remSen": - return getAppImg("remote_sensor_icon.png") - break - case "fanCtrl": - return getAppImg("fan_control_icon.png") - break - case "conWat": - return getAppImg("open_window.png") - break - case "leakWat": - return getAppImg("leak_icon.png") - break - case "extTmp": - return getAppImg("external_temp_icon.png") - break - case "tMode": - return getAppImg("mode_setpoints_icon.png") - break - case "humCtrl": - return getAppImg("humidity_automation_icon.png") - break -*/ case "nMode": return getAppImg("mode_automation_icon.png") break @@ -9565,6 +10115,9 @@ def getAutoIcon(type) { case "watchDog": return getAppImg("watchdog_icon.png") break + case "storage": + return getAppImg("storage_icon.png") + break case "remDiag": return getAppImg("diag_icon.png") break @@ -9586,18 +10139,9 @@ def isSchMotConfigured() { return settings?.schMotTstat ? true : false } -//These are here to catch any events that occur before the migration occurs -def heartbeatAutomation() { return } -def runAutomationEval() { return } -def automationGenericEvt(evt) { return } -def automationSafetyTempEvt(evt) { return } -def nModeGenericEvt(evt) { return } -def leakWatSensorEvt(evt) { return } -def conWatContactEvt(evt) { return } -def extTmpGenericEvt(evt) { return } - def getAutomationType() { - return atomicState?.automationType ?: null + //return atomicState?.automationType ?: null + return null } def getIsAutomationDisabled() { @@ -9613,11 +10157,11 @@ def fixTempSetting(Double temp) { if(temp != null) { if(getTemperatureScale() == "C") { if(temp > 35) { // setting was done in F - newtemp = roundTemp( (newtemp - 32.0) * (5 / 9) as Double) // + newtemp = roundTemp( (newtemp - 32.0) * (5 / 9) as Double) } } else if(getTemperatureScale() == "F") { if(temp < 40) { // setting was done in C - newtemp = roundTemp( ((newtemp * (9 / 5) as Double) + 32.0) ).toInteger() // + newtemp = roundTemp( ((newtemp * (9 / 5) as Double) + 32.0) ).toInteger() } } } @@ -9636,136 +10180,11 @@ private timeDayOfWeekOptions() { return ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] } -/* -private getDayOfWeekName(date = null) { - if (!date) { - date = adjustTime(now()) - } - switch (date.day) { - case 0: return "Sunday" - case 1: return "Monday" - case 2: return "Tuesday" - case 3: return "Wednesday" - case 4: return "Thursday" - case 5: return "Friday" - case 6: return "Saturday" - } - return null -} - -private getDayOfWeekNumber(date = null) { - if (!date) { - date = adjustTime(now()) - } - if (date instanceof Date) { - return date.day - } - switch (date) { - case "Sunday": return 0 - case "Monday": return 1 - case "Tuesday": return 2 - case "Wednesday": return 3 - case "Thursday": return 4 - case "Friday": return 5 - case "Saturday": return 6 - } - return null -} - -//adjusts the time to local timezone -private adjustTime(time = null) { - if (time instanceof String) { - //get UTC time - time = timeToday(time, location.timeZone).getTime() - } - if (time instanceof Date) { - //get unix time - time = time.getTime() - } - if (!time) { - time = now() - } - if (time) { - return new Date(time + location.timeZone.getOffset(time)) - } - return null -} - -private formatLocalTime(time, format = "EEE, MMM d yyyy @ h:mm a z") { - if (time instanceof Long) { - time = new Date(time) - } - if (time instanceof String) { - //get UTC time - time = timeToday(time, location.timeZone) - } - if (!(time instanceof Date)) { - return null - } - def formatter = new java.text.SimpleDateFormat(format) - formatter.setTimeZone(location.timeZone) - return formatter.format(time) -} - -private convertDateToUnixTime(date) { - if (!date) { - return null - } - if (!(date instanceof Date)) { - date = new Date(date) - } - return date.time - location.timeZone.getOffset(date.time) -} - -private convertTimeToUnixTime(time) { - if (!time) { - return null - } - return time - location.timeZone.getOffset(time) -} - -private formatTime(time, zone = null) { - //we accept both a Date or a settings' Time - return formatLocalTime(time, "h:mm a${zone ? " z" : ""}") -} - -private formatHour(h) { - return (h == 0 ? "midnight" : (h < 12 ? "${h} AM" : (h == 12 ? "noon" : "${h-12} PM"))).toString() -} - -def getActiveScheduleState() { - return atomicState?.activeSchedData ?: null -} - -def okSym() { - return "✓"// ☑" -} -def notOkSym() { - return "✘" -} - -def getRemSenTempSrc() { - return atomicState?.remoteTempSourceStr ?: null -} - -def getAbrevDay(vals) { - def list = [] - if(vals) { - //log.debug "days: $vals | (${vals?.size()})" - def len = (vals?.toString().length() < 7) ? 3 : 2 - vals?.each { d -> - list.push(d?.toString().substring(0, len)) - } - } - return list -} -*/ - def roundTemp(Double temp) { if(temp == null) { return null } def newtemp if( getTemperatureScale() == "C") { - newtemp = Math.round(temp.round(1) * 2) / 2.0f // + newtemp = Math.round(temp.round(1) * 2) / 2.0f } else { if(temp instanceof Integer) { //log.debug "roundTemp: ($temp) is Integer" @@ -9785,30 +10204,6 @@ def roundTemp(Double temp) { return newtemp } -/* -def deviceInputToList(items) { - def list = [] - if(items) { - items?.sort().each { d -> - list.push(d?.displayName.toString()) - } - return list - } - return null -} - -def inputItemsToList(items) { - def list = [] - if(items) { - items?.each { d -> - list.push(d) - } - return list - } - return null -} -*/ - def getInputToStringDesc(inpt, addSpace = null) { def cnt = 0 def str = "" @@ -9831,41 +10226,6 @@ def isPluralString(obj) { | GLOBAL Code | Logging AND Diagnostic | *************************************************************************************************/ -def sendEventPushNotifications(message, type, pName) { - //LogTrace("sendEventPushNotifications($message, $type, $pName)") - if(settings["${pName}_Alert_1_Send_Push"] || settings["${pName}_Alert_2_Send_Push"]) { -//TODO this portion is never reached - if(settings["${pName}_Alert_1_CustomPushMessage"]) { - sendNofificationMsg(settings["${pName}_Alert_1_CustomPushMessage"].toString(), type, settings?."${pName}NotifRecips", settings?."${pName}NotifPhones", settings?."${pName}UsePush") - } else { - sendNofificationMsg(message, type, settings?."${pName}NotifRecips", settings?."${pName}NotifPhones", settings?."${pName}UsePush") - } - } else { - sendNofificationMsg(message, type, settings?."${pName}NotifRecips", settings?."${pName}NotifPhones", settings?."${pName}UsePush") - } -} - -def sendEventVoiceNotifications(vMsg, pName, msgId, rmAAMsg=false, rmMsgId) { - def allowNotif = settings?."${pName}NotificationsOn" ? true : false - def allowSpeech = allowNotif && settings?."${pName}AllowSpeechNotif" ? true : false - def ok2Notify = getOk2Notify() - - LogAction("sendEventVoiceNotifications($vMsg, $pName) ok2Notify: $ok2Notify", "trace", false) - if(allowNotif && allowSpeech) { - if(ok2Notify && (settings["${pName}SpeechDevices"] || settings["${pName}SpeechMediaPlayer"])) { - sendTTS(vMsg, pName) - } - if(settings["${pName}SendToAskAlexaQueue"]) { // we queue to Alexa regardless of quiet times - if(rmMsgId != null && rmAAMsg == true) { - removeAskAlexaQueueMsg(rmMsgId) - } - if (vMsg && msgId != null) { - addEventToAskAlexaQueue(vMsg, msgId) - } - } - } -} - def addEventToAskAlexaQueue(vMsg, msgId, queue=null) { if(getAskAlexaMQEn()) { if(getAskAlexaMultiQueueEn()) { @@ -9908,17 +10268,6 @@ def getSafetyTemps(tstat, usedefault=true) { return null } -/* -def getComfortHumidity(tstat) { - def maxHum = tstat?.currentValue("comfortHumidityMax") ?: 0 - if(maxHum) { - //return ["min":minHumidity, "max":maxHumidity] - return maxHum - } - return null -} -*/ - def getComfortDewpoint(tstat, usedefault=true) { def maxDew = tstat?.currentState("comfortDewpointMax")?.doubleValue maxDew = maxDew ?: 0.0 @@ -9936,16 +10285,13 @@ def askAlexaImgUrl() { return "https://raw.githubusercontent.com/MichaelStruck/S /////////////////////////////////////////////////////////////////////////////// /****************************************************************************** -| Application Help and License Info Variables | +| Application Help and License Info Variables | *******************************************************************************/ /////////////////////////////////////////////////////////////////////////////// def appName() { return "${parent ? "${autoAppName()}" : "${appLabel()}"}${appDevName()}" } -def appLabel() { return inReview() ? "NST Manager" : "Nest Manager" } +def appLabel() { return "Nest Manager" } def appAuthor() { return "Anthony S." } def appNamespace() { return "tonesto7" } -def useNewAutoFile() { return true } -def blockOldAuto() { return true } -def newAutoName() { return "NST Automations" } def autoAppName() { return "NST Automations" } def gitRepo() { return "tonesto7/nest-manager"} def gitBranch() { return betaMarker() ? "beta" : "master" } @@ -9953,9 +10299,6 @@ def gitPath() { return "${gitRepo()}/${gitBranch()}"} def developerVer() { return false } def betaMarker() { return false } def appDevType() { return false } -def inReview() { return false } -def keepBackups() { return false } -def allowMigration() { return true } def appDevName() { return appDevType() ? " (Dev)" : "" } def appInfoDesc() { def cur = atomicState?.appData?.updater?.versions?.app?.ver.toString() @@ -9968,11 +10311,11 @@ def appInfoDesc() { } def textVersion() { return "Version: ${appVersion()}" } def textModified() { return "Updated: ${appVerDate()}" } - def textVerInfo() { return "${appVerInfo()}" } def appVerInfo() { return getWebData([uri: "https://raw.githubusercontent.com/${gitPath()}/Data/changelog.txt", contentType: "text/plain; charset=UTF-8"], "changelog") } def textLicense() { return getWebData([uri: "https://raw.githubusercontent.com/${gitPath()}/app_license.txt", contentType: "text/plain; charset=UTF-8"], "license") } -def textDonateLink() { return "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2CJEVN439EAWS" } +def textDonateLink(){ return "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2CJEVN439EAWS" } +def streamLink() { return "https://community.smartthings.com/t/nst-manager-real-time-events/89198" } def stIdeLink() { return "https://graph.api.smartthings.com" } -def textCopyright() { return "Copyright© 2017 - Anthony S." } +def textCopyright() { return "Copyright© 2017, 2018 - Anthony S." } def textDesc() { return "This SmartApp is used to integrate your Nest devices with SmartThings and to enable built-in automations" } diff --git a/smartapps/tonesto7/nst-automations.src/nst-automations.groovy b/smartapps/tonesto7/nst-automations.src/nst-automations.groovy index c1d4314eb..01ebd145d 100644 --- a/smartapps/tonesto7/nst-automations.src/nst-automations.groovy +++ b/smartapps/tonesto7/nst-automations.src/nst-automations.groovy @@ -1,6 +1,6 @@ /******************************************************************************************** | Application Name: NST Automations | -| Copyright (C) 2017 Anthony S. | +| Copyright (C) 2017, 2018, 2019 Anthony S. | | Authors: Anthony S. (@tonesto7), Eric S. (@E_sch) | | Contributors: Ben W. (@desertblade) | | A few code methods are modeled from those in CoRE by Adrian Caramaliu | @@ -18,17 +18,16 @@ definition( parent: "${appNamespace()}:${appParentName()}", description: "${appDesc()}", category: "Convenience", - iconUrl: "https://raw.githubusercontent.com/${gitPath()}/Images/App/automation_icon.png", - iconX2Url: "https://raw.githubusercontent.com/${gitPath()}/Images/App/automation_icon.png", - iconX3Url: "https://raw.githubusercontent.com/${gitPath()}/Images/App/automation_icon.png" -) + iconUrl: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_automations_5.png", + iconX2Url: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_automations_5.png", + iconX3Url: "https://raw.githubusercontent.com/${gitPath()}/Images/App/nst_automations_5.png") { appSetting "devOpt" } -def appVersion() { "5.2.1" } -def appVerDate() { "12-16-2017" } +def appVersion() { "5.5.0" } +def appVerDate() { "01-25-2019" } preferences { //startPage @@ -48,6 +47,7 @@ preferences { page(name: "schMotModePage") page(name: "setDayModeTimePage") page(name: "watchDogPage") + page(name: "storagePage") page(name: "diagnosticsPage") page(name: "schMotSchedulePage") page(name: "scheduleConfigPage") @@ -59,7 +59,7 @@ preferences { } /****************************************************************************** -| Application Pages | +| Application Pages | *******************************************************************************/ //This Page is used to load either parent or child app interface code def startPage() { @@ -70,6 +70,8 @@ def startPage() { atomicState?.isParent = false selectAutoPage() } + } else { + notAllowedPage() } } @@ -79,6 +81,7 @@ def notAllowedPage () { paragraph "HOUSTON WE HAVE A PROBLEM!\n\nNST Automations can't be directly installed from the Marketplace.\n\nPlease use the NST Manager SmartApp to configure them.", required: true, state: null, image: getAppImg("disable_icon2.png") } + remove("Remove this bad Automation", "WARNING!!!", "BAD Automation SHOULD be removed") } } @@ -100,7 +103,7 @@ def uninstallPage() { paragraph "This will uninstall the ${app?.label} Automation!" } } - remove("Remove ${appName()} and Devices!", "WARNING!!!", "Last Chance to Stop!\nThis action is not reversible\n\nThis App, All Devices, and Automations will be removed") + remove("Remove ${appName()}", "WARNING!!!", "Last Chance to Stop!\nThis action is not reversible\n\nThis Automation will be removed") } } @@ -109,16 +112,20 @@ def uninstallPage() { *######################### NATIVE ST APP METHODS ############################* ******************************************************************************/ def installed() { - log.debug "${app.label} Installed with settings: ${settings}" // MUST BE log.debug + log.debug "${app.getLabel()} Installed with settings: ${settings}" // MUST BE log.debug atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString()] + atomicState?.isInstalled = true initialize() + if(settings["storageFlag"]) { + atomicState?.automationType = "storage" + parent?.storageAppInst(true) + } sendNotificationEvent("${appName()} installed") } def updated() { - LogAction("${app.label} Updated...with settings: ${settings}", "debug", true) + LogAction("${app.getLabel()} Updated...with settings: ${settings}", "debug", true) initialize() - sendNotificationEvent("${appName()} has updated settings") atomicState?.lastUpdatedDt = getDtNow() } @@ -131,6 +138,7 @@ def initialize() { //log.debug "${app.label} Initialize..." // Must be log.debug if(!atomicState?.newAutomationFile) { atomicState?.newAutomationFile = true } if(!atomicState?.installData) { atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString()] } + if(!atomicState?.isInstalled) { atomicState?.isInstalled = true } def settingsReset = parent?.settings?.resetAllData if(atomicState?.resetAllData || settingsReset) { if(fixState()) { return } // runIn of fixState will call initAutoApp() @@ -144,12 +152,13 @@ def subscriber() { private adj_temp(tempF) { if(getTemperatureScale() == "C") { - return ((tempF - 32) * (5 / 9)) as Double // + return ((tempF - 32) * ( 5/9 )) as Double } else { return tempF } } +/* def getStZipCode() { return location?.zipCode?.toString() } def getNestZipCode() { if(atomicState?.structures && atomicState?.structData) { @@ -168,20 +177,21 @@ def helpHandler() { atomicState.showHelp = (help?.showHelp == false) ? false : true } } +*/ -def incMetricCntVal(item) { - def data = atomicState?.usageMetricsStore ?: [:] +private incMetricCntVal(String item) { + Map data = atomicState?.usageMetricsStore ?: [:] data[item] = (data[item] == null) ? 1 : data[item].toInteger()+1 atomicState?.usageMetricsStore = data } def incAutoGlobPrefLoadCnt() { incMetricCntVal("autoGlobPrefLoadCnt") } -def isCodeUpdateAvailable(newVer, curVer, type) { - def result = false +Boolean isCodeUpdateAvailable(String newVer, String curVer, String type) { + Boolean result = false def latestVer if(newVer && curVer) { - def versions = [newVer, curVer] + List versions = [newVer, curVer] if(newVer != curVer) { latestVer = versions?.max { a, b -> def verA = a?.tokenize('.') @@ -195,7 +205,7 @@ def isCodeUpdateAvailable(newVer, curVer, type) { } verA?.size() <=> verB?.size() } - result = (latestVer == newVer) ? true : false + result = (latestVer == newVer) } } //log.debug "type: $type | newVer: $newVer | curVer: $curVer | newestVersion: ${latestVer} | result: $result" @@ -220,39 +230,30 @@ def getMyLockId() { def fixState() { def result = false - LogAction("fixState", "info", false) + LogTrace("fixState") def before = getStateSizePerc() - if(!parent) { -/* - if(!atomicState?.resetAllData && resetAllData) { - def data = getState()?.findAll { !(it?.key in ["accessToken", "authToken", "enRemDiagLogging", "installationId", "remDiagLogActivatedDt", "remDiagLogDataStore", "remDiagDataSentDt", "remDiagLogSentCnt", "resetAllData", "pollingOn", "apiCommandCnt"]) } - data.each { item -> - state.remove(item?.key.toString()) - } - unschedule() - unsubscribe() - atomicState.pollingOn = false - result = true - } else if(atomicState?.resetAllData && !resetAllData) { - LogAction("fixState: resetting ALL toggle", "info", true) - atomicState.resetAllData = false - } -*/ - } else { - if(!atomicState?.resetAllData && parent?.settings?.resetAllData) { // automation cleanup called from update() -> initAutoApp() - def data = getState()?.findAll { !(it?.key in [ "automationType", "disableAutomation", "lastScheduleList", "oldremSenTstat", "leakWatRestoreMode", "conWatRestoreMode", "extTmpRestoreMode", "extTmpTstatOffRequested", "conWatTstatOffRequested", "leakWatTstatOffRequested", "resetAllData", "extTmpLastDesiredTemp", "restoreId", "restoredFromBackup", "restoreCompleted", "automationTypeFlag", "newAutomationFile", "installData", "remDiagLogDataStore" ]) } + if(!atomicState?.resetAllData && parent?.settings?.resetAllData) { // automation cleanup called from update() -> initAutoApp() + def data = getState()?.findAll { !(it?.key in [ "automationType", "disableAutomation", "lastScheduleList", "resetAllData", "disableAutomationDt", + "leakWatRestoreMode", "leakWatTstatOffRequested", + "conWatRestoreMode", "conWatlastMode", "conWatTstatOffRequested", + "oldremSenTstat", /* "remSenTstat", */ + "haveRunFan", "lastfanCtrlRunDt", "lastfanCtrlFanOffDt", + "extTmpRestoreMode", "extTmpTstatOffRequested", "extTmpLastDesiredTemp", "extTmplastMode", "extTmpLastDesiredCTemp", "extTmpLastDesiredHTemp", "extTmpChgWhileOnDt", "extTmpChgWhileOffDt", + "remDiagLogDataStore", + "restoreId", "restoredFromBackup", "restoreCompleted", "automationTypeFlag", "newAutomationFile", "installData", "usageMetricsStore" ]) } // "watchDogAlarmActive", "extTmpAlarmActive", "conWatAlarmActive", "leakWatAlarmActive", - data.each { item -> - state.remove(item?.key.toString()) - } - unschedule() - unsubscribe() - result = true - } else if(atomicState?.resetAllData && !parent?.settings?.resetAllData) { - LogAction("fixState: resetting ALL toggle", "info", true) - atomicState.resetAllData = false + data.each { item -> + state.remove(item?.key.toString()) } + setAutomationStatus() + unschedule() + unsubscribe() + result = true + } else if(atomicState?.resetAllData && !parent?.settings?.resetAllData) { + LogAction("fixState: resetting ALL toggle", "info", true) + atomicState.resetAllData = false } + if(result) { atomicState.resetAllData = true LogAction("fixState: State Data: before: $before after: ${getStateSizePerc()}", "info", true) @@ -262,79 +263,28 @@ def fixState() { } void finishFixState(migrate=false) { - LogAction("finishFixState", "info", false) - if(!parent) { -/* - if(atomicState?.resetAllData) { - atomicState.misPollNotifyWaitVal = !misPollNotifyWaitVal ? 900 : misPollNotifyWaitVal.toInteger() - atomicState.misPollNotifyMsgWaitVal = !misPollNotifyMsgWaitVal ? 3600 : misPollNotifyMsgWaitVal.toInteger() - atomicState.updNotifyWaitVal = !updNotifyWaitVal ? 43200 : updNotifyWaitVal.toInteger() - atomicState.useAltNames = settings?.useAltNames ? true : false - atomicState.custLabelUsed = settings?.useCustDevNames ? true : false - if(!atomicState?.installData) { atomicState?.installData = ["initVer":appVersion(), "dt":getDtNow().toString(), "freshInstall":false, "shownDonation":false, "shownFeedback":false] } - - getWebFileData() // get the appData and calls setStateVar - - atomicState.needStrPoll = true - atomicState?.needDevPoll = true - atomicState?.needMetaPoll = true - - atomicState.structures = settings?.structures ?: null - if(settings?.structures && atomicState?.structures && !atomicState.structName) { - def structs = getNestStructures() - if(structs) { - atomicState.structName = "${structs[atomicState?.structures]}" - } - } - //def str = getApiData("str") - //def dev = getApiData("dev") - //def meta = getApiData("meta") - - if(settings?.thermostats && !atomicState?.thermostats) { atomicState.thermostats = settings?.thermostats ? statState(settings?.thermostats) : null } - if(settings?.protects && !atomicState?.protects) { atomicState.protects = settings?.protects ? coState(settings?.protects) : null } - if(settings?.cameras && !atomicState?.cameras) { atomicState.cameras = settings?.cameras ? camState(settings?.cameras) : null } - atomicState.presDevice = settings?.presDevice ?: null - atomicState.weatherDevice = settings?.weatherDevice ?: null - if(settings?.thermostats || settings?.protects || settings?.cameras || settings?.presDevice || settings?.weatherDevice) { - atomicState.isInstalled = true - atomicState.newSetupComplete = true - atomicState?.setupVersion = atomicState?.appData?.updater?.setupVersion?.toInteger() ?: 0 - } else { atomicState.isInstalled = false } - - //updated() - initManagerApp() - - def cApps = getChildApps() - if(cApps) { - cApps?.sort()?.each { chld -> - chld?.update() - } + LogTrace("finishFixState") + if(atomicState?.resetAllData || migrate) { + def tstat = settings?.schMotTstat + if(tstat) { + LogAction("finishFixState found tstat", "info", true) + getTstatCapabilities(tstat, schMotPrefix()) + if(!getMyLockId()) { + setMyLockId(app.id) } - } -*/ - } else { - if(atomicState?.resetAllData || migrate) { - def tstat = settings?.schMotTstat - if(tstat) { - LogAction("finishFixState found tstat", "info", true) - getTstatCapabilities(tstat, schMotPrefix()) - if(!getMyLockId()) { - setMyLockId(app.id) + if(settings?.schMotRemoteSensor) { + LogAction("finishFixState found remote sensor", "info", true) + if( parent?.remSenLock(tstat?.deviceNetworkId, getMyLockId()) ) { // lock new ID + atomicState?.remSenTstat = tstat?.deviceNetworkId } - if(settings?.schMotRemoteSensor) { - LogAction("finishFixState found remote sensor", "info", true) - if( parent?.remSenLock(tstat?.deviceNetworkId, getMyLockId()) ) { // lock new ID - atomicState?.remSenTstat = tstat?.deviceNetworkId - } - if(isRemSenConfigured() && settings?.remSensorDay) { - LogAction("finishFixState found remote sensor configured", "info", true) - if(settings?.vthermostat != null) { parent?.addRemoveVthermostat(tstat.deviceNetworkId, vthermostat, getMyLockId()) } - } + if(isRemSenConfigured() && settings?.remSensorDay) { + LogAction("finishFixState found remote sensor configured", "info", true) + if(settings?.vthermostat != null) { parent?.addRemoveVthermostat(tstat.deviceNetworkId, vthermostat, getMyLockId()) } } } - if(!migrate) { initAutoApp() } - //updated() } + if(!migrate) { initAutoApp() } + //updated() } } @@ -358,18 +308,20 @@ def selectAutoPage() { def mainAutoPage(params) { //LogTrace("mainAutoPage()") - if(!atomicState?.tempUnit) { atomicState?.tempUnit = getTemperatureScale()?.toString() } + def t0 = getTemperatureScale()?.toString() + atomicState?.tempUnit = (t0 != null) ? t0 : atomicState?.tempUnit if(!atomicState?.disableAutomation) { atomicState.disableAutomation = false } - def t0 = parent?.getShowHelp() + t0 = parent?.getShowHelp() atomicState?.showHelp = (t0 != null) ? t0 : true def autoType = null //If params.autoType is not null then save to atomicState. if(!params?.autoType) { autoType = atomicState?.automationType } - else { atomicState.automationType = params?.autoType; autoType = params?.autoType } + else { atomicState.automationType = params?.autoType; autoType = params?.autoType; } // If the selected automation has not been configured take directly to the config page. Else show main page if(autoType == "nMode" && !isNestModesConfigured()) { return nestModePresPage() } else if(autoType == "watchDog" && !isWatchdogConfigured()) { return watchDogPage() } + else if(autoType == "storage") { return storagePage() } else if(autoType == "remDiag" && !isDiagnosticsConfigured()) { return diagnosticsPage() } else if(autoType == "schMot" && !isSchMotConfigured()) { return schMotModePage() } @@ -378,7 +330,7 @@ def mainAutoPage(params) { //return dynamicPage(name: "mainAutoPage", title: "Automation Configuration", uninstall: false, install: false, nextPage: "nameAutoPage" ) { return dynamicPage(name: "mainAutoPage", title: "Automation Configuration", uninstall: false, install: true, nextPage:null ) { section() { - if(disableAutomationreq) { + if(settings?.disableAutomationreq) { paragraph "This Automation is currently disabled!\nTurn it back on to to make changes or resume operation", required: true, state: null, image: getAppImg("instruct_icon.png") } else { if(atomicState?.disableAutomation) { paragraph "This Automation is still disabled!\nPress Next and Done to Activate this Automation Again", state: "complete", image: getAppImg("instruct_icon.png") } @@ -394,7 +346,7 @@ def mainAutoPage(params) { } nDesc += (nModePresSensor && !nModeSwitch) ? "\n\n${nModePresenceDesc()}" : "" nDesc += (nModeSwitch && !nModePresSensor) ? "\n • Using Switch: (State: ${isSwitchOn(nModeSwitch) ? "ON" : "OFF"})" : "" - nDesc += (nModeDelay && nModeDelayVal) ? "\n • Change Delay: (${getEnumValue(longTimeSecEnum(), nModeDelayVal)})" : "" + nDesc += (settings?.nModeDelay && settings?.nModeDelayVal) ? "\n • Change Delay: (${getEnumValue(longTimeSecEnum(), settings?.nModeDelayVal)})" : "" nDesc += (isNestModesConfigured() ) ? "\n • Restrictions Active: (${autoScheduleOk(getAutoType()) ? "NO" : "YES"})" : "" if(isNestModesConfigured()) { nDesc += "\n • Set Thermostats to ECO: (${nModeSetEco ? "On" : "Off"})" @@ -406,7 +358,9 @@ def mainAutoPage(params) { } } } - nDesc += (nModePresSensor || nModeSwitch) || (!nModePresSensor && !nModeSwitch && (nModeAwayModes && nModeHomeModes)) ? "\n\nTap to modify" : "" + def t1 = getNotifConfigDesc("nMode") + nDesc += t1 ? "\n\n${t1}" : "" + nDesc += t1 || (nModePresSensor || nModeSwitch) || (!nModePresSensor && !nModeSwitch && (nModeAwayModes && nModeHomeModes)) ? "\n\nTap to modify" : "" def nModeDesc = isNestModesConfigured() ? "${nDesc}" : null href "nestModePresPage", title: "Nest Mode Automation Config", description: nModeDesc ?: "Tap to configure", state: (nModeDesc ? "complete" : null), image: getAppImg("mode_automation_icon.png") } @@ -419,25 +373,30 @@ def mainAutoPage(params) { if(autoType == "watchDog") { //paragraph title:"Watch your Nest Location for Events:", "" def watDesc = "" - def t1 = getVoiceNotifConfigDesc("watchDog") - watDesc += (settings["${getAutoType()}AllowSpeechNotif"] && (settings["${getAutoType()}SpeechDevices"] || settings["${getAutoType()}SpeechMediaPlayer"]) && t1) ? - "\n\nVoice Notifications:${t1}" : "" + //def t1 = getVoiceNotifConfigDesc("watchDog") + //watDesc += (settings["${getAutoType()}AllowSpeechNotif"] && (settings["${getAutoType()}SpeechDevices"] || settings["${getAutoType()}SpeechMediaPlayer"]) && t1) ? "\n\nVoice Notifications:${t1}" : "" + def t1 = getNotifConfigDesc("watchDog") + watDesc += t1 ? "${t1}\n\nTap to modify" : "" def watDogDesc = isWatchdogConfigured() ? "${watDesc}" : null href "watchDogPage", title: "Nest Location Watchdog", description: watDogDesc ?: "Tap to configure", state: (watDogDesc ? "complete" : null), image: getAppImg("watchdog_icon.png") } if(autoType == "remDiag") { - //paragraph title:"Watch your Nest Location for Events:", "" def diagDesc = "" def remDiagDesc = isDiagnosticsConfigured() ? "${diagDesc}" : null href "diagnosticsPage", title: "NST Diagnostics", description: remDiagDesc ?: "Tap to configure", state: (remDiagDesc ? "complete" : null), image: getAppImg("diag_icon.png") } + if(autoType == "storage") { + def storDesc = "" + def storageDesc = isStorageConfigured() ? "${storDesc}" : null + href "storagePage", title: "NST Storage", description: storageDesc ?: "Tap to configure", state: (storageDesc ? "complete" : null), image: getAppImg("storage_icon.png") + } } } section("Automation Options:") { - if(atomicState?.isInstalled && (isNestModesConfigured() || isWatchdogConfigured() || isSchMotConfigured())) { + if(/* atomicState?.isInstalled && */ (isNestModesConfigured() || isWatchdogConfigured() || isSchMotConfigured())) { //paragraph title:"Enable/Disable this Automation", "" - input "disableAutomationreq", "bool", title: "Disable this Automation?", required: false, defaultValue: atomicState?.disableAutomation, submitOnChange: true, image: getAppImg("disable_icon2.png") - setAutomationStatus(settings?.disableAutomationreq) + input "disableAutomationreq", "bool", title: "Disable this Automation?", required: false, defaultValue: false /* atomicState?.disableAutomation */, submitOnChange: true, image: getAppImg("disable_icon2.png") + setAutomationStatus() } input ("showDebug", "bool", title: "Debug Option", description: "Show Automation Logs in the IDE?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("debug_icon.png")) if(showDebug) { @@ -447,15 +406,11 @@ def mainAutoPage(params) { } } section("Automation Name:") { -// if(autoType == "watchDog") { -// paragraph "${app?.label}" -// } else { - def newName = getAutoTypeLabel() - label title: "Label this Automation:", description: "Suggested Name: ${newName}", defaultValue: newName, required: true, wordWrap: true, image: getAppImg("name_tag_icon.png") - if(!atomicState?.isInstalled) { - paragraph "Make sure to name it something that you can easily recgonize." - } -// } + def newName = getAutoTypeLabel() + label title: "Label this Automation:", description: "Suggested Name: ${newName}", defaultValue: newName, required: true, wordWrap: true, image: getAppImg("name_tag_icon.png") + if(!atomicState?.isInstalled) { + paragraph "Make sure to name it something that you can easily recgonize." + } } remove("Remove this Automation!", "WARNING!!!", "Last Chance to Stop!!!\nThis action is not reversible\n\nThis Automation will be removed completely") } @@ -480,20 +435,31 @@ def getSchMotConfigDesc(retAsList=false) { list?.each { ls -> sDesc += "\n • ${ls}" } + def t1 = getNotifConfigDesc("schMot") + sDesc += t1 ? "\n\n${t1}" : "" sDesc += settings?.schMotTstat ? "\n\nTap to modify" : "" return isSchMotConfigured() ? "${sDesc}" : null } } -def setAutomationStatus(disabled, upd=false) { - if(!atomicState?.disableAutomation && disabled) { +def setAutomationStatus(upd=false) { + Boolean myDis = (settings?.disableAutomationreq == true) + Boolean settingsReset = (parent?.settings?.disableAllAutomations == true) + Boolean storAutoType = getAutoType() == "storage" ? true : false + if(settingsReset && !storAutoType) { + if(!myDis && settingsReset) { LogAction("setAutomationStatus: NST Manager forcing disable", "info", true) } + myDis = true + } else if(storAutoType) { + myDis = false + } + if(!atomicState?.disableAutomation && myDis) { LogAction("Automation Disabled at (${getDtNow()})", "info", true) atomicState?.disableAutomationDt = getDtNow() - } else if(atomicState?.disableAutomation && !disabled) { + } else if(atomicState?.disableAutomation && !myDis) { LogAction("Automation Enabled at (${getDtNow()})", "info", true) atomicState?.disableAutomationDt = null } - atomicState?.disableAutomation = disabled + atomicState?.disableAutomation = myDis if(upd) { app.update() } } @@ -533,8 +499,7 @@ def createAutoBackupJson() { else { if(itemType == "mode" || itemVal instanceof Integer || itemVal instanceof Double || itemVal instanceof Boolean || itemVal instanceof Float || itemVal instanceof Long || itemVal instanceof BigDecimal) { setObj = itemVal - } - else { setObj = itemVal.toString() } + } else { setObj = itemVal.toString() } } //log.debug "setting item ${item?.key}: ${getObjType(itemVal)} | result: $setObj" setData[item?.key]?.value = setObj @@ -560,40 +525,41 @@ def backupConfigToFirebase() { void settingUpdate(name, value, type=null) { LogTrace("settingUpdate($name, $value, $type)...") - try { - //if(name && value && type) { - if(name && type) { - app?.updateSetting("$name", [type: "$type", value: value]) + if(name) { + if(value == "" || value == null || value == []) { + settingRemove(name) + return } - //else if (name && value && type == null) { app?.updateSetting(name.toString(), value) } - else if (name && type == null) { app?.updateSetting(name.toString(), value) } - } catch(e) { - log.error "settingUpdate Exception:", ex } + if(name && type) { app?.updateSetting("$name", [type: "$type", value: value]) } + else if (name && type == null) { app?.updateSetting(name.toString(), value) } +} + +void settingRemove(name) { + LogAction("settingRemove($name)...", "trace", false) + if(name) { app?.deleteSetting("$name") } } def stateUpdate(key, value) { - if(key) { atomicState?."${key}" = value } - else { LogAction("stateUpdate: null key $key $value", "error", true) } + if(key) { atomicState?."${key}" = value; return true } + else { LogAction("stateUpdate: null key $key $value", "error", true); return false } +} + +def stateRemove(key) { + if(state?.containsKey(key)) { state.remove(key?.toString()) } + return true } def initAutoApp() { //log.debug "${app.label} initAutoApp..." // Must be log.debug - def restoreId = settings["restoreId"] - def restoreComplete = settings["restoreCompleted"] == true ? true : false if(settings["watchDogFlag"]) { atomicState?.automationType = "watchDog" + } else if(settings["storageFlag"]) { + atomicState?.automationType = "storage" + parent?.storageAppInst(true) } else if(settings["remDiagFlag"]) { atomicState?.automationType = "remDiag" - } - else if (restoreId != null && restoreComplete == false) { - LogAction("Restored AutomationType: (${settings?.automationTypeFlag})", "info", true) - if(parent?.callRestoreState(app, restoreId)) { - finishFixState(true) - parent?.postChildRestore(restoreId) - if(parent?.keepBackups() != true) { parent?.removeAutomationBackupData(restoreId) } - settingUpdate("restoreCompleted", true, "bool") - } + parent?.remDiagAppAvail(true) } def autoType = getAutoType() @@ -603,92 +569,95 @@ def initAutoApp() { unschedule() unsubscribe() def autoDisabled = getIsAutomationDisabled() + setAutomationStatus() - if(!autoDisabled && (restoreId && restoreComplete == false ? false : true)) { - automationsInst() + //if(!autoDisabled && (restoreId && restoreComplete == false ? false : true)) { - if(autoType == "schMot" && isSchMotConfigured()) { - updateScheduleStateMap() - def schedList = getScheduleList() - def timersActive = false - def sLbl - def cnt = 1 - def numact = 0 - schedList?.each { scd -> - sLbl = "schMot_${scd}_" - atomicState."schedule${cnt}SwEnabled" = null - atomicState."schedule${cnt}PresEnabled" = null - atomicState."schedule${cnt}MotionEnabled" = null - atomicState."schedule${cnt}SensorEnabled" = null - - def newscd = [] - def act = settings["${sLbl}SchedActive"] - if(act) { - newscd = cleanUpMap([ - m: settings["${sLbl}restrictionMode"], - tf: settings["${sLbl}restrictionTimeFrom"], - tfc: settings["${sLbl}restrictionTimeFromCustom"], - tfo: settings["${sLbl}restrictionTimeFromOffset"], - tt: settings["${sLbl}restrictionTimeTo"], - ttc: settings["${sLbl}restrictionTimeToCustom"], - tto: settings["${sLbl}restrictionTimeToOffset"], - w: settings["${sLbl}restrictionDOW"], - p1: buildDeviceNameList(settings["${sLbl}restrictionPresHome"], "and"), - p0: buildDeviceNameList(settings["${sLbl}restrictionPresAway"], "and"), - s1: buildDeviceNameList(settings["${sLbl}restrictionSwitchOn"], "and"), - s0: buildDeviceNameList(settings["${sLbl}restrictionSwitchOff"], "and"), - ctemp: roundTemp(settings["${sLbl}CoolTemp"]), - htemp: roundTemp(settings["${sLbl}HeatTemp"]), - hvacm: settings["${sLbl}HvacMode"], - sen0: settings["schMotRemoteSensor"] ? buildDeviceNameList(settings["${sLbl}remSensor"], "and") : null, - thres: settings["schMotRemoteSensor"] ? settings["${sLbl}remSenThreshold"] : null, - m0: buildDeviceNameList(settings["${sLbl}Motion"], "and"), - mctemp: settings["${sLbl}Motion"] ? roundTemp(settings["${sLbl}MCoolTemp"]) : null, - mhtemp: settings["${sLbl}Motion"] ? roundTemp(settings["${sLbl}MHeatTemp"]) : null, - mhvacm: settings["${sLbl}Motion"] ? settings["${sLbl}MHvacMode"] : null, -// mpresHome: settings["${sLbl}Motion"] ? settings["${sLbl}MPresHome"] : null, -// mpresAway: settings["${sLbl}Motion"] ? settings["${sLbl}MPresAway"] : null, - mdelayOn: settings["${sLbl}Motion"] ? settings["${sLbl}MDelayValOn"] : null, - mdelayOff: settings["${sLbl}Motion"] ? settings["${sLbl}MDelayValOff"] : null - ]) - numact += 1 - } - LogTrace("initAutoApp: [Schedule: $scd | sLbl: $sLbl | act: $act | newscd: $newscd]") - atomicState."sched${cnt}restrictions" = newscd - atomicState."schedule${cnt}SwEnabled" = (newscd?.s1 || newscd?.s0) ? true : false - atomicState."schedule${cnt}PresEnabled" = (newscd?.p1 || newscd?.p0) ? true : false - atomicState."schedule${cnt}MotionEnabled" = (newscd?.m0) ? true : false - atomicState."schedule${cnt}SensorEnabled" = (newscd?.sen0) ? true : false - //atomicState."schedule${cnt}FanCtrlEnabled" = (newscd?.fan0) ? true : false - atomicState."schedule${cnt}TimeActive" = (newscd?.tf || newscd?.tfc || newscd?.tfo || newscd?.tt || newscd?.ttc || newscd?.tto || newscd?.w) ? true : false - - atomicState."${sLbl}MotionActiveDt" = null - atomicState."${sLbl}MotionInActiveDt" = null - - def newact = isMotionActive(settings["${sLbl}Motion"]) - if(newact) { atomicState."${sLbl}MotionActiveDt" = getDtNow() } - else { atomicState."${sLbl}MotionInActiveDt" = getDtNow() } - - atomicState."${sLbl}oldMotionActive" = newact - atomicState?."motion${cnt}UseMotionSettings" = null // clear automation state of schedule in use motion state - atomicState?."motion${cnt}LastisBtwn" = false - - timersActive = (timersActive || atomicState."schedule${cnt}TimeActive") ? true : false + automationsInst() - cnt += 1 + if(autoType == "schMot" && isSchMotConfigured()) { + updateScheduleStateMap() + def schedList = getScheduleList() + def timersActive = false + def sLbl + def cnt = 1 + def numact = 0 + schedList?.each { scd -> + sLbl = "schMot_${scd}_" + atomicState."schedule${cnt}SwEnabled" = null + atomicState."schedule${cnt}PresEnabled" = null + atomicState."schedule${cnt}MotionEnabled" = null + atomicState."schedule${cnt}SensorEnabled" = null + + def newscd = [:] + def act = settings["${sLbl}SchedActive"] + if(act) { + newscd = cleanUpMap([ + m: settings["${sLbl}restrictionMode"], + tf: settings["${sLbl}restrictionTimeFrom"], + tfc: settings["${sLbl}restrictionTimeFromCustom"], + tfo: settings["${sLbl}restrictionTimeFromOffset"], + tt: settings["${sLbl}restrictionTimeTo"], + ttc: settings["${sLbl}restrictionTimeToCustom"], + tto: settings["${sLbl}restrictionTimeToOffset"], + w: settings["${sLbl}restrictionDOW"], + p1: buildDeviceNameList(settings["${sLbl}restrictionPresHome"], "and"), + p0: buildDeviceNameList(settings["${sLbl}restrictionPresAway"], "and"), + s1: buildDeviceNameList(settings["${sLbl}restrictionSwitchOn"], "and"), + s0: buildDeviceNameList(settings["${sLbl}restrictionSwitchOff"], "and"), + ctemp: roundTemp(settings["${sLbl}CoolTemp"]), + htemp: roundTemp(settings["${sLbl}HeatTemp"]), + hvacm: settings["${sLbl}HvacMode"], + sen0: settings["schMotRemoteSensor"] ? buildDeviceNameList(settings["${sLbl}remSensor"], "and") : null, + thres: settings["schMotRemoteSensor"] ? settings["${sLbl}remSenThreshold"] : null, + m0: buildDeviceNameList(settings["${sLbl}Motion"], "and"), + mctemp: settings["${sLbl}Motion"] ? roundTemp(settings["${sLbl}MCoolTemp"]) : null, + mhtemp: settings["${sLbl}Motion"] ? roundTemp(settings["${sLbl}MHeatTemp"]) : null, + mhvacm: settings["${sLbl}Motion"] ? settings["${sLbl}MHvacMode"] : null, +// mpresHome: settings["${sLbl}Motion"] ? settings["${sLbl}MPresHome"] : null, +// mpresAway: settings["${sLbl}Motion"] ? settings["${sLbl}MPresAway"] : null, + mdelayOn: settings["${sLbl}Motion"] ? settings["${sLbl}MDelayValOn"] : null, + mdelayOff: settings["${sLbl}Motion"] ? settings["${sLbl}MDelayValOff"] : null + ]) + numact += 1 } - atomicState.scheduleTimersActive = timersActive - atomicState.lastSched = null // clear automation state of schedule in use - atomicState.scheduleSchedActiveCount = numact - } + LogTrace("initAutoApp: [Schedule: $scd | sLbl: $sLbl | act: $act | newscd: $newscd]") + atomicState."sched${cnt}restrictions" = newscd + atomicState."schedule${cnt}SwEnabled" = (newscd?.s1 || newscd?.s0) ? true : false + atomicState."schedule${cnt}PresEnabled" = (newscd?.p1 || newscd?.p0) ? true : false + atomicState."schedule${cnt}MotionEnabled" = (newscd?.m0) ? true : false + atomicState."schedule${cnt}SensorEnabled" = (newscd?.sen0) ? true : false + //atomicState."schedule${cnt}FanCtrlEnabled" = (newscd?.fan0) ? true : false + atomicState."schedule${cnt}TimeActive" = (newscd?.tf || newscd?.tfc || newscd?.tfo || newscd?.tt || newscd?.ttc || newscd?.tto || newscd?.w) ? true : false + + atomicState."${sLbl}MotionActiveDt" = null + atomicState."${sLbl}MotionInActiveDt" = null - subscribeToEvents() - scheduler() + def newact = isMotionActive(settings["${sLbl}Motion"]) + if(newact) { atomicState."${sLbl}MotionActiveDt" = getDtNow() } + else { atomicState."${sLbl}MotionInActiveDt" = getDtNow() } + + atomicState."${sLbl}oldMotionActive" = newact + atomicState?."motion${cnt}UseMotionSettings" = null // clear automation state of schedule in use motion state + atomicState?."motion${cnt}LastisBtwn" = false + + timersActive = (timersActive || atomicState."schedule${cnt}TimeActive") ? true : false + + cnt += 1 + } + atomicState.scheduleTimersActive = timersActive + atomicState.lastSched = null // clear automation state of schedule in use + atomicState.scheduleSchedActiveCount = numact } + + subscribeToEvents() + scheduler() + app.updateLabel(getAutoTypeLabel()) LogAction("Automation Label: ${getAutoTypeLabel()}", "info", true) - - //if(settings["backedUpData"] && atomicState?.restoreCompleted) { } + if(settings?."${autoType}PushoverEnabled" == true) { + pushover_init() + } else { pushover_cleanup() } state.remove("motionnullLastisBtwn") state.remove("motion1InBtwn") @@ -718,21 +687,14 @@ def uninstAutomationApp() { //LogTrace("uninstAutomationApp") def autoType = getAutoType() if(autoType == "schMot") { - def myID = getMyLockId() - if(schMotTstat && myID && parent) { - if(parent?.addRemoveVthermostat(schMotTstat.deviceNetworkId, false, myID)) { - LogAction("uninstAutomationApp: cleanup virtual thermostat", "debug", true) - } - } - if(schMotTstat && myID && parent) { - if( parent?.remSenUnlock(atomicState?.remSenTstat, myID) ) { // attempt unlock old ID - LogAction("uninstAutomationApp: Released remote sensor lock", "debug", true) - } - } + removeVstat("uninstAutomationApp") } if(autoType == "nMode") { parent?.automationNestModeEnabled(false) } + if(settings["remDiagFlag"]) { + parent?.remDiagAppAvail(false) + } } def getCurAppLbl() { return app?.label?.toString() } @@ -748,6 +710,7 @@ def getAutoTypeLabel() { if(type == "nMode") { typeLabel = "${newName} (NestMode)" } else if(type == "watchDog") { typeLabel = "Nest Location ${location.name} Watchdog"} + else if(type == "storage") { typeLabel = "NST Storage"} else if(type == "remDiag") { typeLabel = "NST Diagnostics"} else if(type == "schMot") { typeLabel = "${newName} (${schMotTstat?.label})" } @@ -783,26 +746,27 @@ def getStateVal(var) { return state[var] ?: null } -def automationsInst() { - atomicState.isNestModesConfigured = isNestModesConfigured() ? true : false - atomicState.isWatchdogConfigured = isWatchdogConfigured() ? true : false - atomicState.isDiagnosticsConfigured = isDiagnosticsConfigured() ? true : false - atomicState.isSchMotConfigured = isSchMotConfigured() ? true : false - - atomicState.isLeakWatConfigured = isLeakWatConfigured() ? true : false - atomicState.isConWatConfigured = isConWatConfigured() ? true : false - atomicState.isHumCtrlConfigured = isHumCtrlConfigured() ? true : false - atomicState.isExtTmpConfigured = isExtTmpConfigured() ? true : false - atomicState.isRemSenConfigured = isRemSenConfigured() ? true : false - atomicState.isTstatSchedConfigured = isTstatSchedConfigured() ? true : false - atomicState.isFanCtrlConfigured = isFanCtrlSwConfigured() ? true : false - atomicState.isFanCircConfigured = isFanCircConfigured() ? true : false +public automationsInst() { + atomicState.isNestModesConfigured = (isNestModesConfigured() == true) + atomicState.isWatchdogConfigured = (isWatchdogConfigured() == true) + atomicState.isDiagnosticsConfigured = (isDiagnosticsConfigured() == true) + atomicState.isStorageConfigured = (isStorageConfigured() == true) + atomicState.isSchMotConfigured = (isSchMotConfigured() == true) + + atomicState.isLeakWatConfigured = (isLeakWatConfigured() == true) + atomicState.isConWatConfigured = (isConWatConfigured() == true) + atomicState.isHumCtrlConfigured = (isHumCtrlConfigured() == true) + atomicState.isExtTmpConfigured = (isExtTmpConfigured() == true) + atomicState.isRemSenConfigured = (isRemSenConfigured() == true) + atomicState.isTstatSchedConfigured = (isTstatSchedConfigured() == true) + atomicState.isFanCtrlConfigured = (isFanCtrlSwConfigured() == true) + atomicState.isFanCircConfigured = (isFanCircConfigured() == true) atomicState?.isInstalled = true } -def getAutomationsInstalled() { - def list = [] - def aType = atomicState?.automationType +List getAutomationsInstalled() { + List list = [] + String aType = atomicState?.automationType switch(aType) { case "nMode": list.push(aType) @@ -810,14 +774,14 @@ def getAutomationsInstalled() { case "schMot": def tmp = [:] tmp[aType] = [] - if(isLeakWatConfigured()) { tmp[aType].push("leakWat") } - if(isConWatConfigured()) { tmp[aType].push("conWat") } - if(isHumCtrlConfigured()) { tmp[aType].push("humCtrl") } - if(isExtTmpConfigured()) { tmp[aType].push("extTmp") } + if(isLeakWatConfigured()) { tmp[aType].push("leakWat") } + if(isConWatConfigured()) { tmp[aType].push("conWat") } + if(isHumCtrlConfigured()) { tmp[aType].push("humCtrl") } + if(isExtTmpConfigured()) { tmp[aType].push("extTmp") } if(isRemSenConfigured()) { tmp[aType].push("remSen") } - if(isTstatSchedConfigured()) { tmp[aType].push("tSched") } - if(isFanCtrlSwConfigured()) { tmp[aType].push("fanCtrl") } - if(isFanCircConfigured()) { tmp[aType].push("fanCirc") } + if(isTstatSchedConfigured()) { tmp[aType].push("tSched") } + if(isFanCtrlSwConfigured()) { tmp[aType].push("fanCtrl") } + if(isFanCircConfigured()) { tmp[aType].push("fanCirc") } if(tmp?.size()) { list.push(tmp) } break case "watchDog": @@ -826,16 +790,19 @@ def getAutomationsInstalled() { case "remDiag": list.push(aType) break + case "storage": + list.push(aType) + break } LogTrace("getAutomationsInstalled List: $list") return list } -def getAutomationType() { +String getAutomationType() { return atomicState?.automationType ?: null } -def getAutoType() { return !parent ? "" : atomicState?.automationType } +String getAutoType() { return !parent ? "" : atomicState?.automationType } def getIsAutomationDisabled() { def dis = atomicState?.disableAutomation @@ -844,8 +811,8 @@ def getIsAutomationDisabled() { def subscribeToEvents() { //Remote Sensor Subscriptions - def autoType = getAutoType() - def swlist = [] + String autoType = getAutoType() + List swlist = [] //Nest Mode Subscriptions if(autoType == "nMode") { @@ -862,13 +829,13 @@ def subscribeToEvents() { if(d1) { LogAction("Found: ${d1?.displayName} with (Id: ${dni?.key})", "debug", false) - subscribe(d1, "nestThermostatMode", automationGenericEvt) - subscribe(d1, "presence", automationGenericEvt) + //subscribe(d1, "nestThermostatMode", automationGenericEvt) // this is not needed for nMode + //subscribe(d1, "presence", automationGenericEvt) // this is not needed, tracking only } return d1 } } - def t0 = [] + List t0 = [] if(settings["nModerestrictionSwitchOn"]) { t0 = t0 + settings["nModerestrictionSwitchOn"] } if(settings["nModerestrictionSwitchOff"]) { t0 = t0 + settings["nModerestrictionSwitchOff"] } for(sw in t0) { @@ -890,12 +857,18 @@ def subscribeToEvents() { if(isSchMotConfigured()) { if(settings?.schMotWaterOff) { - if(isLeakWatConfigured()) { subscribe(leakWatSensors, "water", leakWatSensorEvt) } + if(isLeakWatConfigured()) { + setInitialVoiceMsgs(leakWatPrefix()) + setCustomVoice(leakWatPrefix()) + subscribe(leakWatSensors, "water", leakWatSensorEvt) + } } if(settings?.schMotContactOff) { if(isConWatConfigured()) { + setInitialVoiceMsgs(conWatPrefix()) + setCustomVoice(conWatPrefix()) subscribe(conWatContacts, "contact", conWatContactEvt) - def t0 = [] + List t0 = [] if(settings["conWatrestrictionSwitchOn"]) { t0 = t0 + settings["conWatrestrictionSwitchOn"] } if(settings["conWatrestrictionSwitchOff"]) { t0 = t0 + settings["conWatrestrictionSwitchOff"] } for(sw in t0) { @@ -938,6 +911,8 @@ def subscribeToEvents() { if(settings?.schMotExternalTempOff) { if(isExtTmpConfigured()) { + setInitialVoiceMsgs(extTmpPrefix()) + setCustomVoice(extTmpPrefix()) if(settings?.extTmpUseWeather) { atomicState.needWeathUpd = true if(parent?.getWeatherDeviceInst()) { @@ -975,13 +950,18 @@ def subscribeToEvents() { senlist.push(sen) subscribe(sen, "temperature", automationGenericEvt) subscribe(sen, "humidity", automationGenericEvt) + if(settings?.schMotExternalTempOff) { + if(isExtTmpConfigured()) { + subscribe(sen, "temperature", extTmpGenericEvt) + subscribe(sen, "humidity", extTmpGenericEvt) + } + } } } } } } - if(isTstatSchedConfigured()) { - } + if(isTstatSchedConfigured()) { } if(settings?.schMotOperateFan) { if(isFanCtrlSwConfigured() && fanCtrlFanSwitches) { subscribe(fanCtrlFanSwitches, "switch", automationGenericEvt) @@ -999,15 +979,16 @@ def subscribeToEvents() { } } } - if(settings?.schMotOperateFan || settings?.schMotRemoteSensor || settings?.schMotHumidityControl) { + Boolean hasFan = (atomicState?.schMotTstatHasFan == true) + if(hasFan && (settings?.schMotOperateFan || settings?.schMotRemoteSensor || settings?.schMotHumidityControl)) { subscribe(schMotTstat, "thermostatFanMode", automationGenericEvt) } - def schedList = getScheduleList() - def sLbl - def cnt = 1 - def prlist = [] - def mtlist = [] + List schedList = getScheduleList() + String sLbl + Integer cnt = 1 + List prlist = [] + List mtlist = [] schedList?.each { scd -> sLbl = "schMot_${scd}_" def restrict = atomicState?."sched${cnt}restrictions" @@ -1089,8 +1070,14 @@ def subscribeToEvents() { subscribe(schMotTstat, "thermostatOperatingState", automationGenericEvt) subscribe(schMotTstat, "temperature", automationGenericEvt) subscribe(schMotTstat, "presence", automationGenericEvt) - subscribe(schMotTstat, "coolingSetpoint", automationGenericEvt) - subscribe(schMotTstat, "heatingSetpoint", automationGenericEvt) + def canCool = atomicState?.schMotTstatCanCool + if(canCool) { + subscribe(schMotTstat, "coolingSetpoint", automationGenericEvt) + } + def canHeat = atomicState?.schMotTstatCanHeat + if(canHeat) { + subscribe(schMotTstat, "heatingSetpoint", automationGenericEvt) + } subscribe(schMotTstat, "safetyTempExceeded", automationSafetyTempEvt) subscribe(location, "sunset", automationGenericEvt) subscribe(location, "sunrise", automationGenericEvt) @@ -1099,7 +1086,7 @@ def subscribeToEvents() { } //watchDog Subscriptions if(autoType == "watchDog") { - // if(isWatchdogConfigured()) { + // if(isWatchdogConfigured()) def tstats = parent?.getTstats() def foundTstats @@ -1119,11 +1106,12 @@ def subscribeToEvents() { return d1 } } - //Alarm status monitoring - if(settings["${autoType}AlarmDevices"] && settings?."${pName}AllowAlarmNotif") { - if(settings["${autoType}_Alert_1_Use_Alarm"] || settings["${autoType}_Alert_2_Use_Alarm"]) { - subscribe(settings["${autoType}AlarmDevices"], "alarm", alarmAlertEvt) - } + } + + //Alarm status monitoring if any automation has alarm notification enabled + if(settings["${autoType}AlarmDevices"] && settings?."${pName}AllowAlarmNotif") { + if(settings["${autoType}_Alert_1_Use_Alarm"] || settings["${autoType}_Alert_2_Use_Alarm"]) { + subscribe(settings["${autoType}AlarmDevices"], "alarm", alarmAlertEvt) } } @@ -1131,6 +1119,11 @@ def subscribeToEvents() { if(autoType == "remDiag") { } + + //storage Subscriptions + if(autoType == "storage") { + + } } def scheduler() { @@ -1142,7 +1135,7 @@ def scheduler() { if(autoType == "schMot" && atomicState?.scheduleSchedActiveCount && atomicState?.scheduleTimersActive) { LogAction("${autoType} scheduled (${random_int} ${random_dint}/5 * * * ?)", "info", true) schedule("${random_int} ${random_dint}/5 * * * ?", heartbeatAutomation) - } else if(autoType != "remDiag") { + } else if(autoType != "remDiag" || autoType != "storage") { LogAction("${autoType} scheduled (${random_int} ${random_dint}/30 * * * ?)", "info", true) schedule("${random_int} ${random_dint}/30 * * * ?", heartbeatAutomation) } @@ -1156,7 +1149,7 @@ def heartbeatAutomation() { val = 220 } if(getLastAutomationSchedSec() > val) { - LogAction("${autoType} Heartbeat run", "trace", false) + LogTrace("${autoType} Heartbeat run") runAutomationEval() } } @@ -1243,7 +1236,12 @@ def runAutomationEval() { break case "remDiag": if(isDiagnosticsConfigured()) { - //remDiagCheck() + // remDiagCheck() + } + break + case "storage": + if(isStorageConfigured()) { + // storageCheck() } break default: @@ -1342,7 +1340,7 @@ def doTheEvent(evt) { } /****************************************************************************** -| WATCHDOG AUTOMATION LOGIC CODE | +| WATCHDOG AUTOMATION LOGIC CODE | *******************************************************************************/ def watchDogPrefix() { return "watchDog" } @@ -1350,9 +1348,10 @@ def watchDogPage() { def pName = watchDogPrefix() dynamicPage(name: "watchDogPage", title: "Nest Location Watchdog", uninstall: false, install: true) { section("Notifications:") { - def pageDesc = getNotifConfigDesc(pName) + def t0 = getNotifConfigDesc(pName) + def pageDesc = t0 ? "${t0}\n\nTap to modify" : "" href "setNotificationPage", title: "Configured Alerts", description: pageDesc, params: ["pName":"${pName}", "allowSpeech":true, "allowAlarm":true, "showSchedule":true], - state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") + state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") input "watDogNotifMissedEco", "bool", title: "Notify When Away and Not in Eco Mode?", required: false, defaultValue: true, submitOnChange: true, image: getAppImg("switch_on_icon.png") } //remove("Remove ${app?.label}!", "Last Chance!!!", "Warning!!! This action is not reversible\n\nThis Automation will be removed completely") @@ -1411,7 +1410,6 @@ def watchDogCheck() { def watchDogAlarmActions(dev, dni, actType) { def pName = watchDogPrefix() - //def allowNotif = (settings["${pName}NotificationsOn"] && (settings["${pName}NotifRecips"] || settings["${pName}NotifPhones"] || settings["${pName}UsePush"])) ? true : false def allowNotif = settings["${pName}NotificationsOn"] ? true : false def allowSpeech = allowNotif && settings?."${pName}AllowSpeechNotif" ? true : false def allowAlarm = allowNotif && settings?."${pName}AllowAlarmNotif" ? true : false @@ -1429,25 +1427,25 @@ def watchDogAlarmActions(dev, dni, actType) { } else {return} break } - if(getLastWatDogSafetyAlertDtSec(dni) > getWatDogRepeatMsgDelayVal()) { + if(getLastWatDogSafetyAlertDtSec("${dni?.key}") > getWatDogRepeatMsgDelayVal()) { LogAction("watchDogAlarmActions() | ${evtNotifMsg}", "warn", true) if(allowNotif) { - sendEventPushNotifications(evtNotifMsg, "Warning", pName) + sendEventPushNotifications(evtNotifMsg, "Warning", pName) // this uses parent and honors quiet times others do NOT if(allowSpeech) { sendEventVoiceNotifications(voiceNotifString(evtVoiceMsg, pName), pName, "nmWatDogEvt_${app?.id}", true, "nmWatDogEvt_${app?.id}") } if(allowAlarm) { scheduleAlarmOn(pName) } + atomicState?."lastWatDogSafetyAlertDt${dni?.key}" = getDtNow() } else { - sendNofificationMsg("Warning", evtNotifMsg) + //sendNofificationMsg(evtNotifMsg, "Warning", watchDogPrefix()) } - atomicState?."lastWatDogSafetyAlertDt${dni}" = getDtNow() } } -def getLastWatDogSafetyAlertDtSec(dni) { return !atomicState?."lastWatDogSafetyAlertDt{$dni}" ? 10000 : GetTimeDiffSeconds(atomicState?."lastWatDogSafetyAlertDt${dni}", null, "getLastWatDogSafetyAlertDtSec").toInteger() } +def getLastWatDogSafetyAlertDtSec(dni) { return !atomicState?."lastWatDogSafetyAlertDt${dni}" ? 10000 : GetTimeDiffSeconds(atomicState?."lastWatDogSafetyAlertDt${dni}", null, "getLastWatDogSafetyAlertDtSec").toInteger() } def getWatDogRepeatMsgDelayVal() { return !watDogRepeatMsgDelay ? 3600 : watDogRepeatMsgDelay.toInteger() } def isWatchdogConfigured() { @@ -1455,7 +1453,7 @@ def isWatchdogConfigured() { } /****************************************************************************** -| REMOTE DIAG AUTOMATION LOGIC CODE | +| REMOTE DIAG AUTOMATION LOGIC CODE | *******************************************************************************/ def remDiagPrefix() { return "remDiag" } @@ -1468,6 +1466,27 @@ def diagnosticsPage() { } } +def storagePrefix() { return "storage" } +def storagePage() { + def pName = storagePrefix() + dynamicPage(name: "storagePage", title: "NST Storage", uninstall: false, install: true) { + storageInfoSect() + } +} + +def storageInfoSect() { + section("Storage App Info:") { + def str = "" + str += "Version: V${appVersion()}" + str += "\nUsage: ${getStateSizePerc()}%" + paragraph str, state: "complete" + } +} + +def isStorageConfigured() { + return (atomicState?.automationType == "storage") ? true : false +} + def isDiagnosticsConfigured() { return (atomicState?.automationType == "remDiag") ? true : false } @@ -1476,11 +1495,41 @@ def isDiagnosticsConfigured() { /////////////////////THERMOSTAT AUTOMATION CODE LOGIC /////////////////////// /**************************************************************************** -| REMOTE SENSOR AUTOMATION CODE | +| REMOTE SENSOR AUTOMATION CODE | *****************************************************************************/ def remSenPrefix() { return "remSen" } +//ERS +def removeVstat(callerStr) { + def autoType = getAutoType() + if(autoType == "schMot") { + def mycallerStr = "${callerStr} removeVstat: Could" + def t0 = mycallerStr + def myID = getMyLockId() + if(!myID) { + setMyLockId(app.id) + myID = getMyLockId() + } + def toRemove = atomicState?.remSenTstat + if(schMotTstat && myID && parent && toRemove) { + + if(!parent?.addRemoveVthermostat(toRemove, false, myID)) { + t0 = "${mycallerStr} NOT" + } + LogAction("${t0} cleanup virtual thermostat", "debug", true) + atomicState.oldremSenTstat = atomicState?.remSenTstat + atomicState?.remSenTstat = null + + t0 = mycallerStr + if( !parent?.remSenUnlock(toRemove, myID) ) { // attempt unlock old ID + t0 = "${mycallerStr} NOT" + } + LogAction("${t0} Release remote sensor lock", "debug", true) + } + } +} + /* def remSenLock(val, myId) { def res = false @@ -1518,7 +1567,7 @@ def remSenDayCoolTempOk() { return (!remSenCoolTempsReq() || (remSenCoolTempsReq def isRemSenConfigured() { def devOk = (settings?.remSensorDay) ? true : false - return (devOk && settings?.remSenRuleType && remSenDayHeatTempOk() && remSenDayCoolTempOk() ) ? true : false + return (settings?.schMotRemoteSensor && devOk && settings?.remSenRuleType && remSenDayHeatTempOk() && remSenDayCoolTempOk() ) ? true : false } def getLastMotionActiveSec(mySched) { @@ -1609,7 +1658,7 @@ def getDeviceTempAvg(items) { if(!items) { return tempVal } else if(items?.size() > 1) { tmpAvg = items*.currentTemperature - if(tmpAvg && tmpAvg?.size() > 1) { tempVal = (tmpAvg?.sum().toDouble() / tmpAvg?.size().toDouble()).round(1) } // + if(tmpAvg && tmpAvg?.size() > 1) { tempVal = (tmpAvg?.sum().toDouble() / tmpAvg?.size().toDouble()).round(1) } } else { tempVal = getDeviceTemp(items) } return tempVal.toDouble() @@ -1618,14 +1667,15 @@ def getDeviceTempAvg(items) { def remSenShowTempsPage() { dynamicPage(name: "remSenShowTempsPage", uninstall: false) { if(settings?.remSensorDay) { + def t0 = "${tUnitStr()}" section("Default Sensor Temps: (Schedules can override)") { def cnt = 0 def rCnt = settings?.remSensorDay?.size() def str = "" - str += "Sensor Temp (average): (${getDeviceTempAvg(settings?.remSensorDay)}°${getTemperatureScale()})\n│" + str += "Sensor Temp (average): (${getDeviceTempAvg(settings?.remSensorDay)}${t0})\n│" settings?.remSensorDay?.each { t -> cnt = cnt+1 - str += "${(cnt >= 1) ? "${(cnt == rCnt) ? "\n└" : "\n├"}" : "\n└"} ${t?.label}: ${(t?.label?.toString()?.length() > 10) ? "\n${(rCnt == 1 || cnt == rCnt) ? " " : "│"}└ " : ""}(${getDeviceTemp(t)}°${getTemperatureScale()})" + str += "${(cnt >= 1) ? "${(cnt == rCnt) ? "\n└" : "\n├"}" : "\n└"} ${t?.label}: ${(t?.label?.toString()?.length() > 10) ? "\n${(rCnt == 1 || cnt == rCnt) ? " " : "│"}└ " : ""}(${getDeviceTemp(t)}${t0})" } paragraph "${str}", state: "complete", image: getAppImg("temperature_icon.png") } @@ -1638,7 +1688,7 @@ def remSendoSetCool(chgval, onTemp, offTemp) { def remSenTstatMir = settings?.schMotTstatMir try { - def hvacMode = remSenTstat ? remSenTstat?.currentThermostatMode.toString() : null + def hvacMode = remSenTstat ? remSenTstat?.currentThermostatMode?.toString() : null def curCoolSetpoint = getTstatSetpoint(remSenTstat, "cool") def curHeatSetpoint = getTstatSetpoint(remSenTstat, "heat") def tempChangeVal = !remSenTstatTempChgVal ? 5.0 : Math.min(Math.max(remSenTstatTempChgVal.toDouble(), 2.0), 5.0) @@ -1646,24 +1696,27 @@ def remSendoSetCool(chgval, onTemp, offTemp) { chgval = (chgval > (onTemp + maxTempChangeVal)) ? onTemp + maxTempChangeVal : chgval chgval = (chgval < (offTemp - maxTempChangeVal)) ? offTemp - maxTempChangeVal : chgval + + def t0 = "${tUnitStr()}" + if(chgval != curCoolSetpoint) { - scheduleAutomationEval(60) + scheduleAutomationEval(70) def cHeat = null if(hvacMode in ["auto"]) { if(curHeatSetpoint >= (offTemp-tempChangeVal)) { cHeat = offTemp - tempChangeVal - LogAction("Remote Sensor: HEAT - Adjusting HeatSetpoint to (${cHeat}°${getTemperatureScale()}) to allow COOL setting", "info", true) + LogAction("Remote Sensor: HEAT - Adjusting HeatSetpoint to (${cHeat}${t0}) to allow COOL setting", "info", true) if(remSenTstatMir) { remSenTstatMir*.setHeatingSetpoint(cHeat) } } } if(setTstatAutoTemps(remSenTstat, chgval, cHeat, "remSen")) { - //LogAction("Remote Sensor: COOL - Adjusting CoolSetpoint to (${chgval}°${getTemperatureScale()}) ", "info", true) - //storeLastAction("Adjusted Cool Setpoint to (${chgval}°${getTemperatureScale()}) Heat Setpoint to (${cHeat}°${getTemperatureScale()})", getDtNow(), "remSen") + //LogAction("Remote Sensor: COOL - Adjusting CoolSetpoint to (${chgval}${t0}) ", "info", true) + //storeLastAction("Adjusted Cool Setpoint to (${chgval}${t0}) Heat Setpoint to (${cHeat}${t0})", getDtNow(), "remSen") if(remSenTstatMir) { remSenTstatMir*.setCoolingSetpoint(chgval) } } return true // let all this take effect } else { - LogAction("Remote Sensor: COOL - CoolSetpoint is already (${chgval}°${getTemperatureScale()}) ", "info", true) + LogAction("Remote Sensor: COOL - CoolSetpoint is already (${chgval}${t0}) ", "info", true) } } catch (ex) { @@ -1678,7 +1731,7 @@ def remSendoSetHeat(chgval, onTemp, offTemp) { def remSenTstatMir = schMotTstatMir try { - def hvacMode = remSenTstat ? remSenTstat?.currentThermostatMode.toString() : null + def hvacMode = remSenTstat ? remSenTstat?.currentThermostatMode?.toString() : null def curCoolSetpoint = getTstatSetpoint(remSenTstat, "cool") def curHeatSetpoint = getTstatSetpoint(remSenTstat, "heat") def tempChangeVal = !remSenTstatTempChgVal ? 5.0 : Math.min(Math.max(remSenTstatTempChgVal.toDouble(), 2.0), 5.0) @@ -1686,24 +1739,27 @@ def remSendoSetHeat(chgval, onTemp, offTemp) { chgval = (chgval < (onTemp - maxTempChangeVal)) ? onTemp - maxTempChangeVal : chgval chgval = (chgval > (offTemp + maxTempChangeVal)) ? offTemp + maxTempChangeVal : chgval + + def t0 = "${tUnitStr()}" + if(chgval != curHeatSetpoint) { - scheduleAutomationEval(60) + scheduleAutomationEval(70) def cCool = null if(hvacMode in ["auto"]) { if(curCoolSetpoint <= (offTemp+tempChangeVal)) { cCool = offTemp + tempChangeVal - LogAction("Remote Sensor: COOL - Adjusting CoolSetpoint to (${cCool}°${getTemperatureScale()}) to allow HEAT setting", "info", true) + LogAction("Remote Sensor: COOL - Adjusting CoolSetpoint to (${cCool}${t0}) to allow HEAT setting", "info", true) if(remSenTstatMir) { remSenTstatMir*.setCoolingSetpoint(cCool) } } } if(setTstatAutoTemps(remSenTstat, cCool, chgval, "remSen")) { - //LogAction("Remote Sensor: HEAT - Adjusting HeatSetpoint to (${chgval}°${getTemperatureScale()})", "info", true) - //storeLastAction("Adjusted Heat Setpoint to (${chgval}°${getTemperatureScale()}) Cool Setpoint to (${cCool}°${getTemperatureScale()})", getDtNow(), "remSen") + //LogAction("Remote Sensor: HEAT - Adjusting HeatSetpoint to (${chgval}${t0})", "info", true) + //storeLastAction("Adjusted Heat Setpoint to (${chgval}${t0}) Cool Setpoint to (${cCool}${t0})", getDtNow(), "remSen") if(remSenTstatMir) { remSenTstatMir*.setHeatingSetpoint(chgval) } } return true // let all this take effect } else { - LogAction("Remote Sensor: HEAT - HeatSetpoint is already (${chgval}°${getTemperatureScale()})", "info", true) + LogAction("Remote Sensor: HEAT - HeatSetpoint is already (${chgval}${t0})", "info", true) } } catch (ex) { @@ -1740,7 +1796,8 @@ private remSenCheck() { } else { //log.info "remSenCheck: Evaluating Event" - def hvacMode = remSenTstat ? remSenTstat?.currentnestThermostatMode.toString() : null + def tempScaleStr = "${tUnitStr()}" + def hvacMode = remSenTstat ? remSenTstat?.currentnestThermostatMode?.toString() : null if(hvacMode in [ "off", "eco"] ) { LogAction("Remote Sensor: Skipping Evaluation; The Current Thermostat Mode is '${strCapitalize(hvacMode)}'", "info", true) disableOverrideTemps() @@ -1765,7 +1822,7 @@ private remSenCheck() { def tempChangeVal = !remSenTstatTempChgVal ? 5.0 : Math.min(Math.max(remSenTstatTempChgVal.toDouble(), 2.0), 5.0) def maxTempChangeVal = tempChangeVal * 3 def curTstatTemp = getDeviceTemp(remSenTstat).toDouble() - def curSenTemp = (settings?.remSensorDay) ? getRemoteSenTemp().toDouble() : null + def curSenTemp = getRemoteSenTemp().toDouble() def curTstatOperState = remSenTstat?.currentThermostatOperatingState.toString() def curTstatFanMode = remSenTstat?.currentThermostatFanMode.toString() @@ -1872,7 +1929,7 @@ private remSenCheck() { } def coolDiff1 = Math.abs(curTstatTemp - curCoolSetpoint) LogAction("Remote Sensor: COOL - coolDiff1: ${coolDiff1} tempChangeVal: ${tempChangeVal}", "trace", false) - if(coolDiff1 < (tempChangeVal / 2)) { // + if(coolDiff1 < (tempChangeVal / 2)) { chg = true LogAction("Remote Sensor: COOL - Adjusting CoolSetpoint to maintain state", "info", true) } @@ -1884,7 +1941,7 @@ private remSenCheck() { } } else { - LogAction("Remote Sensor: NO CHANGE TO COOL - CoolSetpoint is (${curCoolSetpoint}°${getTemperatureScale()}) ", "info", false) + LogAction("Remote Sensor: NO CHANGE TO COOL - CoolSetpoint is (${curCoolSetpoint}${tempScaleStr}) ", "info", false) } } } @@ -1943,7 +2000,7 @@ private remSenCheck() { return // let all this take effect } } else { - LogAction("Remote Sensor: NO CHANGE TO HEAT - HeatSetpoint is already (${curHeatSetpoint}°${getTemperatureScale()})", "info", false) + LogAction("Remote Sensor: NO CHANGE TO HEAT - HeatSetpoint is already (${curHeatSetpoint}${tempScaleStr})", "info", false) } } } @@ -1975,17 +2032,19 @@ def getRemSenTempsToList() { } if(!sensors) { sensors = settings?.remSensorDay } if(sensors?.size() >= 1) { + def t0 = "${tUnitStr()}" def info = [] sensors?.sort().each { - info.push("${it?.displayName}": " ${it?.currentTemperature.toString()}°${getTemperatureScale()}") + info.push("${it?.displayName}": " ${it?.currentTemperature.toString()}${t0}") } return info } } def getDeviceTemp(dev) { - def temp = dev?.currentValue("temperature") ? dev?.currentValue("temperature").toString()?.replaceAll("\\[|\\]", "") : 0 - return temp && "$temp"?.isNumber() ? temp?.toDouble() : 0 + def t0 = dev?.currentValue("temperature") + def temp = t0 ? t0?.toString()?.replaceAll("\\[|\\]", "") : 0 + return temp && "$temp"?.isNumber() ? temp?.toDouble() : 0 } def getTstatSetpoint(tstat, type) { @@ -2019,8 +2078,8 @@ def getRemoteSenThreshold() { def getRemoteSenTemp() { def mySched = getCurrentSchedule() - if(!atomicState.remoteTempSourceStr) { atomicState.remoteTempSourceStr = null } - if(!atomicState.currentSchedNum) { atomicState.currentSchedNum = null } + if(atomicState?.remoteTempSourceStr != null) { atomicState.remoteTempSourceStr = null } + if(atomicState?.currentSchedNum != null) { atomicState.currentSchedNum = null } def sens if(mySched) { def sLbl = "schMot_${mySched}_" @@ -2031,12 +2090,11 @@ def getRemoteSenTemp() { return getDeviceTempAvg(sens).toDouble() } } - if(settings?.remSensorDay) { + if(isRemSenConfigured()) { atomicState.remoteTempSourceStr = "Remote Sensor" atomicState.currentSchedNum = null return getDeviceTempAvg(settings?.remSensorDay).toDouble() - } - else { + } else { atomicState.remoteTempSourceStr = "Thermostat" atomicState.currentSchedNum = null return getDeviceTemp(schMotTstat).toDouble() @@ -2048,16 +2106,16 @@ def getRemoteSenTemp() { } } -def fixTempSetting(Double temp) { - def newtemp = temp +def fixTempSetting(temp) { + Double newtemp = temp?.toDouble() if(temp != null) { if(getTemperatureScale() == "C") { if(temp > 35) { // setting was done in F - newtemp = roundTemp( ((newtemp - 32.0) * (5 / 9)) as Double) // + newtemp = roundTemp( ((newtemp - 32.0) * (5 / 9)) as Double) } } else if(getTemperatureScale() == "F") { if(temp < 40) { // setting was done in C - newtemp = roundTemp( (((newtemp * (9 / 5)) as Double) + 32.0) ).toInteger() // + newtemp = roundTemp( (((newtemp * (9 / 5)) as Double) + 32.0) ).toInteger() } } } @@ -2069,17 +2127,19 @@ def setRemoteSenTstat(val) { atomicState.remSenTstat = val } -def getRemSenCoolSetTemp(curMode=null, useCurrent=true) { - def coolTemp +def getRemSenCoolSetTemp(curMode=null, isEco=false, useCurrent=true) { + Double coolTemp def theMode = curMode != null ? curMode : null if(theMode == null) { def tstat = schMotTstat theMode = tstat ? tstat?.currentnestThermostatMode.toString() : null } + atomicState.remoteCoolSetSourceStr = "" if(theMode != "eco") { if(getLastOverrideCoolSec() < (3600 * 4)) { if(atomicState?.coolOverride != null) { coolTemp = fixTempSetting(atomicState?.coolOverride.toDouble()) + atomicState.remoteCoolSetSourceStr = "Remote Sensor Override" } } else { atomicState?.coolOverride = null } @@ -2089,38 +2149,62 @@ def getRemSenCoolSetTemp(curMode=null, useCurrent=true) { def useMotion = atomicState?."motion${mySched}UseMotionSettings" def hvacSettings = atomicState?."sched${mySched}restrictions" coolTemp = !useMotion ? hvacSettings?.ctemp : hvacSettings?.mctemp ?: hvacSettings?.ctemp + atomicState.remoteCoolSetSourceStr = "Schedule" } - if(coolTemp == null && remSenDayCoolTemp) { - coolTemp = remSenDayCoolTemp.toDouble() - } +// ERS if Remsensor is enabled + if(isRemSenConfigured()) { + if(theMode == "cool" && coolTemp == null /* && isEco */) { + if(atomicState?.extTmpLastDesiredTemp) { + coolTemp = atomicState?.extTmpLastDesiredTemp.toDouble() + atomicState.remoteCoolSetSourceStr = "Last Desired Temp" + } + } + if(theMode == "auto" && coolTemp == null /* && isEco */) { + if(atomicState?.extTmpLastDesiredCTemp) { + coolTemp = atomicState?.extTmpLastDesiredCTemp.toDouble() + atomicState.remoteCoolSetSourceStr = "Last Desired CTemp" + } + } - if(coolTemp == null) { - def desiredCoolTemp = getGlobalDesiredCoolTemp() - if(desiredCoolTemp) { coolTemp = desiredCoolTemp.toDouble() } - } + if(coolTemp == null && remSenDayCoolTemp) { + coolTemp = remSenDayCoolTemp.toDouble() + atomicState.remoteCoolSetSourceStr = "RemSen Day Cool Temp" + } - if(coolTemp) { - coolTemp = fixTempSetting(coolTemp) + if(coolTemp == null) { + def desiredCoolTemp = getGlobalDesiredCoolTemp() + if(desiredCoolTemp) { + coolTemp = desiredCoolTemp.toDouble() + atomicState.remoteCoolSetSourceStr = "Global Desired Cool Temp" + } + } + + if(coolTemp) { + coolTemp = fixTempSetting(coolTemp) + } } } } if(coolTemp == null && useCurrent) { coolTemp = schMotTstat ? getTstatSetpoint(schMotTstat, "cool") : coolTemp + atomicState.remoteCoolSetSourceStr = "Thermostat" } return coolTemp } -def getRemSenHeatSetTemp(curMode=null, useCurrent=true) { - def heatTemp +def getRemSenHeatSetTemp(curMode=null, isEco=false, useCurrent=true) { + Double heatTemp def theMode = curMode != null ? curMode : null if(theMode == null) { def tstat = schMotTstat theMode = tstat ? tstat?.currentnestThermostatMode.toString() : null } + atomicState.remoteHeatSetSourceStr = "" if(theMode != "eco") { if(getLastOverrideHeatSec() < (3600 * 4)) { if(atomicState?.heatOverride != null) { heatTemp = fixTempSetting(atomicState.heatOverride.toDouble()) + atomicState.remoteHeatSetSourceStr = "Remote Sensor Override" } } else { atomicState?.heatOverride = null } @@ -2130,24 +2214,46 @@ def getRemSenHeatSetTemp(curMode=null, useCurrent=true) { def useMotion = atomicState?."motion${mySched}UseMotionSettings" def hvacSettings = atomicState?."sched${mySched}restrictions" heatTemp = !useMotion ? hvacSettings?.htemp : hvacSettings?.mhtemp ?: hvacSettings?.htemp + atomicState.remoteHeatSetSourceStr = "Schedule" } - if(heatTemp == null && remSenDayHeatTemp) { - heatTemp = remSenDayHeatTemp.toDouble() - } +// ERS if Remsensor is enabled + if(isRemSenConfigured()) { + if(theMode == "heat" && heatTemp == null /* && isEco */) { + if(atomicState?.extTmpLastDesiredTemp) { + heatTemp = atomicState?.extTmpLastDesiredTemp.toDouble() + atomicState.remoteHeatSetSourceStr = "Last Desired Temp" + } + } + if(theMode == "auto" && heatTemp == null /* && isEco */) { + if(atomicState?.extTmpLastDesiredHTemp) { + heatTemp = atomicState?.extTmpLastDesiredHTemp.toDouble() + atomicState.remoteHeatSetSourceStr = "Last Desired HTemp" + } + } - if(heatTemp == null) { - def desiredHeatTemp = getGlobalDesiredHeatTemp() - if(desiredHeatTemp) { heatTemp = desiredHeatTemp.toDouble() } - } + if(heatTemp == null && remSenDayHeatTemp) { + heatTemp = remSenDayHeatTemp.toDouble() + atomicState.remoteHeatSetSourceStr = "RemSen Day Heat Temp" + } + + if(heatTemp == null) { + def desiredHeatTemp = getGlobalDesiredHeatTemp() + if(desiredHeatTemp) { + heatTemp = desiredHeatTemp.toDouble() + atomicState.remoteHeatSetSourceStr = "Global Desired Heat Temp" + } + } - if(heatTemp) { - heatTemp = fixTempSetting(heatTemp) + if(heatTemp) { + heatTemp = fixTempSetting(heatTemp) + } } } } if(heatTemp == null && useCurrent) { heatTemp = schMotTstat ? getTstatSetpoint(schMotTstat, "heat") : heatTemp + atomicState.remoteHeatSetSourceStr = "Thermostat" } return heatTemp } @@ -2236,7 +2342,7 @@ def remSenRuleEnum(type=null) { } /************************************************************************ -| FAN CONTROL AUTOMATION CODE | +| FAN CONTROL AUTOMATION CODE | *************************************************************************/ def fanCtrlPrefix() { return "fanCtrl" } @@ -2253,10 +2359,6 @@ def isFanCircConfigured() { return (settings?.schMotOperateFan && settings?.schMotCirculateTstatFan && settings?.schMotFanRuleType) ? true : false } -def getTempScaleStr() { - return "°${getTemperatureScale()}" -} - def getFanSwitchDesc(showOpt = true) { def swDesc = "" def swCnt = 0 @@ -2282,7 +2384,7 @@ def getFanSwitchDesc(showOpt = true) { swDesc += (settings?.schMotCirculateTstatFan) ? "\n • Fan Circulation Enabled" : "" swDesc += (settings?.schMotCirculateTstatFan) ? "\n • Fan Circulation Rule:\n └(${getEnumValue(remSenRuleEnum("fan"), settings?.schMotFanRuleType)})" : "" - swDesc += (settings?.schMotCirculateTstatFan && settings?.fanCtrlTempDiffDegrees) ? ("\n • Threshold: (${settings?.fanCtrlTempDiffDegrees}${getTempScaleStr()})") : "" + swDesc += (settings?.schMotCirculateTstatFan && settings?.fanCtrlTempDiffDegrees) ? ("\n • Threshold: (${settings?.fanCtrlTempDiffDegrees}${tUnitStr()})") : "" swDesc += (settings?.schMotCirculateTstatFan && settings?.fanCtrlOnTime) ? ("\n • Circulate Time: (${getEnumValue(fanTimeSecEnum(), settings?.fanCtrlOnTime)})") : "" swDesc += (settings?.schMotCirculateTstatFan && settings?.fanCtrlTimeBetweenRuns) ? ("\n • Time Between Cycles:\n └ (${getEnumValue(longTimeSecEnum(), settings?.fanCtrlTimeBetweenRuns)})") : "" @@ -2315,10 +2417,33 @@ def fanCtrlCheck() { def execTime = now() //atomicState?.lastEvalDt = getDtNow() - def reqHeatSetPoint = getRemSenHeatSetTemp() - reqHeatSetPoint = reqHeatSetPoint ?: 0 + def curMode = schMotTstat ? schMotTstat?.currentnestThermostatMode?.toString() : null + def modeEco = (curMode in ["eco"]) ? true : false - def reqCoolSetPoint = getRemSenCoolSetTemp() + def reqHeatSetPoint + def reqCoolSetPoint + if(!modeEco) { + reqHeatSetPoint = getRemSenHeatSetTemp(curMode) + reqCoolSetPoint = getRemSenCoolSetTemp(curMode) + } + + def lastMode = schMotTstat ? schMotTstat?.currentpreviousthermostatMode?.toString() : null + if(!lastMode && modeEco && isRemSenConfigured()) { + if( /* !lastMode && */ atomicState?.extTmpTstatOffRequested && atomicState?.extTmplastMode) { + lastMode = atomicState?.extTmplastMode + } + } + if(lastMode) { + if(!reqHeatSetpoint) { reqHeatSetPoint = getRemSenHeatSetTemp(lastMode, modeEco, false) } + if(!reqCoolSetpoint) { reqCoolSetPoint = getRemSenCoolSetTemp(lastMode, modeEco, false) } + if(isRemSenConfigured()) { + if(!reqHeatSetPoint) { reqHeatSetPoint = atomicState?.extTmpLastDesiredHTemp } + if(!reqCoolSetPoint) { reqCoolSetPoint = atomicState?.extTmpLastDesiredCTemp } + } + LogAction("fanCtrlCheck: Using lastMode: ${lastMode} | extTmpTstatOffRequested: ${atomicState?.extTmpTstatOffRequested} | curMode: ${curMode}", "debug", true) + } + + reqHeatSetPoint = reqHeatSetPoint ?: 0 reqCoolSetPoint = reqCoolSetPoint ?: 0 def curTstatTemp = getRemoteSenTemp().toDouble() @@ -2327,13 +2452,13 @@ def fanCtrlCheck() { def curSetPoint = t0 ? t0.toDouble() : 0 def tempDiff = Math.abs(curSetPoint - curTstatTemp) - LogAction("fanCtrlCheck: Desired Temps - Heat: ${reqHeatSetPoint} | Cool: ${reqCoolSetPoint}", "info", false) - LogAction("fanCtrlCheck: Current Thermostat Sensor Temp: ${curTstatTemp} Temp Difference: (${tempDiff})", "info", false) + LogAction("fanCtrlCheck: Desired Temps - Heat: ${reqHeatSetPoint} | Cool: ${reqCoolSetPoint}", "info", true) + LogAction("fanCtrlCheck: Current Thermostat Sensor Temp: ${curTstatTemp} Temp Difference: (${tempDiff})", "info", true) if(isFanCircConfigured()) { def adjust = (getTemperatureScale() == "C") ? 0.5 : 1.0 def threshold = !fanCtrlTempDiffDegrees ? adjust : fanCtrlTempDiffDegrees.toDouble() - def hvacMode = schMotTstat ? schMotTstat?.currentnestThermostatMode.toString() : null + def hvacMode = curMode /* def curTstatFanMode = schMotTstat?.currentThermostatFanMode.toString() def fanOn = (curTstatFanMode == "on" || curTstatFanMode == "circulate") ? true : false @@ -2485,26 +2610,27 @@ def doFanOperation(tempDiff, curTstatTemp, curHeatSetpoint, curCoolSetpoint) { } } if(swOn && atomicState?.haveRunFan && checkFanSpeedSupport(sw)) { - def speed = sw?.currentValue("currentState") ?: null + def t0 = sw?.currentValue("currentState") + def speed = t0 ?: null if(settings?."${pName}FanSwitchSpeedCtrl" && settings?."${pName}FanSwitchHighSpeed" && settings?."${pName}FanSwitchMedSpeed" && settings?."${pName}FanSwitchLowSpeed") { if(tempDiff < settings?."${pName}FanSwitchMedSpeed".toDouble()) { if(speed != "LOW") { sw.lowSpeed() - LogAction("doFanOperation: Temp Difference (${tempDiff}°${getTemperatureScale()}) is BELOW the Medium Speed Threshold of (${settings?."${pName}FanSwitchMedSpeed"}) | Turning '${sw}' Fan Switch on (LOW SPEED)", "info", true) + LogAction("doFanOperation: Temp Difference (${tempDiff}${tUnitStr()}) is BELOW the Medium Speed Threshold of (${settings?."${pName}FanSwitchMedSpeed"}) | Turning '${sw}' Fan Switch on (LOW SPEED)", "info", true) storeLastAction("Set Fan $sw to Low Speed", getDtNow(), pName) } } else if(tempDiff >= settings?."${pName}FanSwitchMedSpeed".toDouble() && tempDiff < settings?."${pName}FanSwitchHighSpeed".toDouble()) { if(speed != "MED") { sw.medSpeed() - LogAction("doFanOperation: Temp Difference (${tempDiff}°${getTemperatureScale()}) is ABOVE the Medium Speed Threshold of (${settings?."${pName}FanSwitchMedSpeed"}) | Turning '${sw}' Fan Switch on (MEDIUM SPEED)", "info", true) + LogAction("doFanOperation: Temp Difference (${tempDiff}${tUnitStr()}) is ABOVE the Medium Speed Threshold of (${settings?."${pName}FanSwitchMedSpeed"}) | Turning '${sw}' Fan Switch on (MEDIUM SPEED)", "info", true) storeLastAction("Set Fan $sw to Medium Speed", getDtNow(), pName) } } else if(tempDiff >= settings?."${pName}FanSwitchHighSpeed".toDouble()) { if(speed != "HIGH") { sw.highSpeed() - LogAction("doFanOperation: Temp Difference (${tempDiff}°${getTemperatureScale()}) is ABOVE the High Speed Threshold of (${settings?."${pName}FanSwitchHighSpeed"}) | Turning '${sw}' Fan Switch on (HIGH SPEED)", "info", true) + LogAction("doFanOperation: Temp Difference (${tempDiff}${tUnitStr()}) is ABOVE the High Speed Threshold of (${settings?."${pName}FanSwitchHighSpeed"}) | Turning '${sw}' Fan Switch on (HIGH SPEED)", "info", true) storeLastAction("Set Fan $sw to High Speed", getDtNow(), pName) } } @@ -2550,7 +2676,7 @@ def circulateFanControl(operType, Double curSenTemp, Double reqSetpointTemp, Dou def fanOn = (curTstatFanMode == "on" || curTstatFanMode == "circulate") ? true : false def returnToAuto = can_Circ ? false : true - if(hvacMode in ["off", "eco"]) { returnToAuto = true } + if(hvacMode in ["off", "eco"]) { returnToAuto = true } // This overrides ECO... // Track approximate fan on / off times if( !fanOn && atomicState?.lastfanCtrlRunDt > atomicState?.lastfanCtrlFanOffDt ) { @@ -2641,6 +2767,7 @@ def circulateFanControl(operType, Double curSenTemp, Double reqSetpointTemp, Dou def getCirculateFanTempOk(Double senTemp, Double reqsetTemp, Double threshold, Boolean fanOn, operType) { def turnOn = false + def tempScaleStr = "${tUnitStr()}" /* def adjust = (getTemperatureScale() == "C") ? 0.5 : 1.0 if(threshold > (adjust * 2.0)) { @@ -2652,11 +2779,11 @@ def getCirculateFanTempOk(Double senTemp, Double reqsetTemp, Double threshold, B return false } - LogAction(" ├ adjust: ${adjust}}°${getTemperatureScale()}", "debug", false) + LogAction(" ├ adjust: ${adjust}}${tUnitStr()}", "debug", false) */ - LogAction(" ├ operType: (${strCapitalize(operType)}) | Temp Threshold: ${threshold}°${getTemperatureScale()} | FanAlreadyOn: (${strCapitalize(fanOn)})", "debug", false) - LogAction(" ├ Sensor Temp: ${senTemp}°${getTemperatureScale()} | Requested Setpoint Temp: ${reqsetTemp}°${getTemperatureScale()}", "debug", false) + LogAction(" ├ operType: (${strCapitalize(operType)}) | Temp Threshold: ${threshold}${tempScaleStr} | FanAlreadyOn: (${strCapitalize(fanOn)})", "debug", false) + LogAction(" ├ Sensor Temp: ${senTemp}${tempScaleStr} | Requested Setpoint Temp: ${reqsetTemp}${tempScaleStr}", "debug", false) if(!reqsetTemp) { LogAction("getCirculateFanTempOk: Bad reqsetTemp ${reqsetTemp}", "warn", false) @@ -2680,8 +2807,8 @@ def getCirculateFanTempOk(Double senTemp, Double reqsetTemp, Double threshold, B // if((senTemp < offtemp) && (senTemp >= (ontemp + adjust))) { turnOn = true } } -// LogAction(" ├ onTemp: ${ontemp} | offTemp: ${offtemp}}°${getTemperatureScale()}", "debug", false) - LogAction(" ├ offTemp: ${offtemp}°${getTemperatureScale()} | Temp Threshold: ${threshold}°${getTemperatureScale()}", "debug", false) +// LogAction(" ├ onTemp: ${ontemp} | offTemp: ${offtemp}}${tempScaleStr}", "debug", false) + LogAction(" ├ offTemp: ${offtemp}${tempScaleStr} | Temp Threshold: ${threshold}${tempScaleStr}", "debug", false) LogAction(" ┌ Final Result: (${strCapitalize(turnOn)})", "debug", false) // LogAction("getCirculateFanTempOk: ", "debug", false) @@ -2711,12 +2838,12 @@ def getCirculateFanTempOk(Double senTemp, Double reqsetTemp, Double threshold, B /******************************************************************************** -| HUMIDITY CONTROL AUTOMATION CODE | +| HUMIDITY CONTROL AUTOMATION CODE | *********************************************************************************/ def humCtrlPrefix() { return "humCtrl" } def isHumCtrlConfigured() { - return ((settings?.humCtrlUseWeather || settings?.humCtrlTempSensor) && settings?.humCtrlHumidity && settings?.humCtrlSwitches) ? true : false + return (settings?.schMotHumidityControl && (settings?.humCtrlUseWeather || settings?.humCtrlTempSensor) && settings?.humCtrlHumidity && settings?.humCtrlSwitches) ? true : false } def getDeviceVarAvg(items, var) { @@ -2725,7 +2852,7 @@ def getDeviceVarAvg(items, var) { if(!items) { return tempVal } else { tmpAvg = items*."${var}" - if(tmpAvg && tmpAvg?.size() > 0) { tempVal = (tmpAvg?.sum().toDouble() / tmpAvg?.size().toDouble()).round(1) } // + if(tmpAvg && tmpAvg?.size() > 0) { tempVal = (tmpAvg?.sum().toDouble() / tmpAvg?.size().toDouble()).round(1) } } return tempVal.toDouble() } @@ -2761,7 +2888,8 @@ def humCtrlHumidityDesc() { str += "Sensor Humidity (average): (${getDeviceVarAvg(settings.humCtrlHumidity, "currentHumidity")}%)" settings?.humCtrlHumidity?.sort { it?.displayName }?.each { dev -> cnt = cnt+1 - def val = strCapitalize(dev?.currentHumidity) ?: "Not Set" + def t0 = strCapitalize(dev?.currentHumidity) + def val = t0 ?: "Not Set" str += "${(cnt >= 1) ? "${(cnt == cCnt) ? "\n└" : "\n├"}" : "\n└"} ${dev?.label}: ${(dev?.label?.toString()?.length() > 10) ? "\n${(cCnt == 1 || cnt == cCnt) ? " " : "│"}└ " : ""}(${val}%)" } return str @@ -2914,14 +3042,16 @@ def humCtrlCheck() { /******************************************************************************** -| EXTERNAL TEMP AUTOMATION CODE | +| EXTERNAL TEMP AUTOMATION CODE | *********************************************************************************/ def extTmpPrefix() { return "extTmp" } def isExtTmpConfigured() { - return ((settings?.extTmpUseWeather || settings?.extTmpTempSensor) && settings?.extTmpDiffVal) ? true : false + return (settings?.schMotExternalTempOff && (settings?.extTmpUseWeather || settings?.extTmpTempSensor) && settings?.extTmpDiffVal) ? true : false } +def getLastextConditionsEvalSec() { return !atomicState?.lastgetExtCond ? 100000 : GetTimeDiffSeconds(atomicState?.lastgetExtCond, null, "getLastextConditionsEvalSec").toInteger() } + def getExtConditions( doEvent = false ) { LogTrace("getExtConditions") if(atomicState?.weatherDeviceInst == null) { @@ -2931,34 +3061,39 @@ def getExtConditions( doEvent = false ) { } //log.debug "set weatherDeviceInst to ${atomicState?.weatherDeviceInst}" } - if(atomicState?.needWeathUpd && atomicState?.weatherDeviceInst) { + if(atomicState?.needWeathUpd && atomicState?.weatherDeviceInst && getLastextConditionsEvalSec() > 15) { try { + atomicState?.lastgetExtCond = getDtNow() def cur = parent?.getWData() def weather = parent.getWeatherDevice() - if(cur && weather && cur?.current_observation) { - atomicState?.curWeather = cur?.current_observation - atomicState?.curWeatherTemp_f = Math.round(cur?.current_observation?.temp_f) as Integer - atomicState?.curWeatherTemp_c = Math.round(cur?.current_observation?.temp_c.toDouble()) - atomicState?.curWeatherLoc = cur?.current_observation?.display_location?.full.toString() // This is not available as attribute in dth - //atomicState?.curWeatherHum = cur?.current_observation?.relative_humidity?.toString().replaceAll("\\%", "") + if(cur && weather /* && cur?.current_observation */) { + atomicState?.curWeather = cur + atomicState?.curWeatherTemp_f = getTemperatureScale() == "C" ? Math.round(cur?.temperature * 9/5 + 32) : Math.round(cur?.temperature) as Integer + atomicState?.curWeatherTemp_c = getTemperatureScale() == "C" ? Math.round(cur?.temperature.toDouble()) : Math.round( ((cur?.temperature - 32) * 5/9) as Double) + + def curLoc = parent?.getWLocation() + atomicState?.curWeatherLoc = curLoc?.location?.city + curLoc?.location?.adminDistrict // This is not available as attribute in dth + //atomicState?.curWeatherHum = cur?.relativeHumidity def dp = 0.0 if(weather) { // Dewpoint is calculated in dth - dp = weather?.currentValue("dewpoint")?.toString().replaceAll("\\[|\\]", "").toDouble() + def t0 = weather?.currentValue("dewpoint") + dp = t0 ? t0?.toString()?.replaceAll("\\[|\\]", "")?.toDouble() : 0.0 } def c_temp = 0.0 def f_temp = 0 as Integer if(getTemperatureScale() == "C") { c_temp = dp as Double - f_temp = ((c_temp * (9 / 5)) + 32) as Integer // + f_temp = ((c_temp * (9 / 5)) + 32) as Integer } else { f_temp = dp as Integer - c_temp = ((f_temp - 32) * (5 / 9)) as Double // + c_temp = ((f_temp - 32) * (5 / 9)) as Double } - atomicState?.curWeatherDewpointTemp_c = Math.round(c_temp.round(1) * 2) / 2.0f // + atomicState?.curWeatherDewpointTemp_c = Math.round(c_temp.round(1) * 2) / 2.0f atomicState?.curWeatherDewpointTemp_f = Math.round(f_temp) as Integer + atomicState?.lastgetExtCond = getDtNow() atomicState.needWeathUpd = false } } catch (ex) { @@ -2993,7 +3128,7 @@ def getExtTmpDewPoint() { def getDesiredTemp() { def extTmpTstat = settings?.schMotTstat - def curMode = extTmpTstat.currentnestThermostatMode.toString() + def curMode = extTmpTstat ? extTmpTstat?.currentnestThermostatMode?.toString() : null def modeOff = (curMode in ["off"]) ? true : false def modeEco = (curMode in ["eco"]) ? true : false def modeCool = (curMode == "cool") ? true : false @@ -3009,8 +3144,10 @@ def getDesiredTemp() { //atomicState?.extTmpLastDesiredTemp } if(lastMode) { - desiredHeatTemp = getRemSenHeatSetTemp(lastMode, false) - desiredCoolTemp = getRemSenCoolSetTemp(lastMode, false) + desiredHeatTemp = getRemSenHeatSetTemp(lastMode, modeEco, false) + desiredCoolTemp = getRemSenCoolSetTemp(lastMode, modeEco, false) + if(!desiredHeatTemp) { desiredHeatTemp = atomicState?.extTmpLastDesiredHTemp } + if(!desiredCoolTemp) { desiredCoolTemp = atomicState?.extTmpLastDesiredCTemp } LogAction("getDesiredTemp: Using lastMode: ${lastMode} | extTmpTstatOffRequested: ${atomicState?.extTmpTstatOffRequested} | curMode: ${curMode}", "debug", false) modeOff = (lastMode in ["off"]) ? true : false modeCool = (lastMode == "cool") ? true : false @@ -3024,7 +3161,7 @@ def getDesiredTemp() { if(desiredHeatTemp && modeHeat) { desiredTemp = desiredHeatTemp } else if(desiredCoolTemp && modeCool) { desiredTemp = desiredCoolTemp } else if(desiredHeatTemp && desiredCoolTemp && (desiredHeatTemp < desiredCoolTemp) && modeAuto ) { - desiredTemp = (desiredCoolTemp + desiredHeatTemp) / 2.0 // + desiredTemp = (desiredCoolTemp + desiredHeatTemp) / 2.0 } //else if(desiredHeatTemp && modeEco) { desiredTemp = desiredHeatTemp } //else if(desiredCoolTemp && modeEco) { desiredTemp = desiredCoolTemp } @@ -3051,7 +3188,7 @@ def extTmpTempOk(disp=false, last=false) { def curDp = getExtTmpDewPoint() def diffThresh = Math.abs(getExtTmpTempDiffVal()) - def curMode = extTmpTstat.currentnestThermostatMode.toString() + def curMode = extTmpTstat ? extTmpTstat?.currentnestThermostatMode?.toString() : null def modeOff = (curMode == "off") ? true : false def modeCool = (curMode == "cool") ? true : false def modeHeat = (curMode == "heat") ? true : false @@ -3064,7 +3201,8 @@ def extTmpTempOk(disp=false, last=false) { LogAction("extTmpTempOk: Inside Temp: ${intTemp} | curMode: ${curMode} | modeOff: ${modeOff} | modeEco: ${modeEco} | modeAuto: ${modeAuto} || extTmpTstatOffRequested: ${atomicState?.extTmpTstatOffRequested}", "debug", false) def retval = true - def tempOk = true + def externalTempOk = true + def internalTempOk = true def dpOk = (curDp < dpLimit || !canCool) ? true : false if(!dpOk) { retval = false } @@ -3085,17 +3223,22 @@ def extTmpTempOk(disp=false, last=false) { if(!getSafetyTempsOk(extTmpTstat)) { retval = false - tempOk = false + externalTempOk = false str = "within safety Temperatures " LogAction("extTmpTempOk: Safety Temps not OK", "warn", true) } + if(modeOff) { + retval = false + } + def desiredHeatTemp def desiredCoolTemp if(modeAuto && retval) { desiredHeatTemp = getRemSenHeatSetTemp(curMode) desiredCoolTemp = getRemSenCoolSetTemp(curMode) } + def lastMode = extTmpTstat?.currentpreviousthermostatMode?.toString() if(curMode == "eco") { if(!lastMode && atomicState?.extTmpTstatOffRequested && atomicState?.extTmplastMode) { @@ -3104,8 +3247,8 @@ def extTmpTempOk(disp=false, last=false) { } if(lastMode) { LogAction("extTmpTempOk: Resetting mode curMode: ${curMode} | to previous mode lastMode: ${lastMode} | extTmpTstatOffRequested: ${atomicState?.extTmpTstatOffRequested}", "debug", false) - desiredHeatTemp = getRemSenHeatSetTemp(lastMode, false) - desiredCoolTemp = getRemSenCoolSetTemp(lastMode, false) + desiredHeatTemp = getRemSenHeatSetTemp(lastMode, modeEco, false) + desiredCoolTemp = getRemSenCoolSetTemp(lastMode, modeEco, false) if(!desiredHeatTemp) { desiredHeatTemp = atomicState?.extTmpLastDesiredHTemp } if(!desiredCoolTemp) { desiredCoolTemp = atomicState?.extTmpLastDesiredCTemp } //modeOff = (lastMode == "off") ? true : false @@ -3119,9 +3262,10 @@ def extTmpTempOk(disp=false, last=false) { if(modeAuto && retval && desiredHeatTemp && desiredCoolTemp) { if( !(extTemp >= (desiredHeatTemp+diffThresh) && extTemp <= (desiredCoolTemp-diffThresh)) ) { retval = false - tempOk = false + externalTempOk = false str = "within range (${desiredHeatTemp} ${desiredCoolTemp})" } +//ERS atomicState?.extTmpLastDesiredHTemp = desiredHeatTemp atomicState?.extTmpLastDesiredCTemp = desiredCoolTemp } @@ -3132,6 +3276,8 @@ def extTmpTempOk(disp=false, last=false) { if(!modeAuto && retval) { desiredTemp = getDesiredTemp() +//ERS + if(desiredTemp) { atomicState?.extTmpLastDesiredTemp = desiredTemp } if(!desiredTemp) { desiredTemp = intTemp if(!modeOff) { @@ -3142,36 +3288,36 @@ def extTmpTempOk(disp=false, last=false) { tempDiff = Math.abs(extTemp - desiredTemp) str = "enough different (${tempDiff})" insideThresh = getExtTmpInsideTempDiffVal() - LogAction("extTmpTempOk: Outside Temp: ${extTemp} | Desired Temp: ${desiredTemp} | Inside Temp Threshold: ${insideThresh} | Outside Temp Threshold: ${diffThresh} | Actual Difference: ${tempDiff} | Outside Dew point: ${curDp} | Dew point Limit: ${dpLimit}", "debug", false) + LogAction("extTmpTempOk: Outside Temp: ${extTemp} | Inside Temp: ${intTemp} | Desired Temp: ${desiredTemp} | Inside Temp Threshold: ${insideThresh} | Outside Temp Threshold: ${diffThresh} | Actual Difference: ${tempDiff} | Outside Dew point: ${curDp} | Dew point Limit: ${dpLimit}", "debug", true) if(diffThresh && tempDiff < diffThresh) { retval = false - tempOk = false + externalTempOk = false } def extTempHigh = (extTemp >= desiredTemp) ? true : false def extTempLow = (extTemp <= desiredTemp) ? true : false def oldMode = atomicState?.extTmpRestoreMode if(modeCool || oldMode == "cool" || (!canHeat && canCool)) { str = "greater than" - if(extTempHigh) { retval = false; tempOk = false } - else if (intTemp > desiredTemp+insideThresh) { retval = false; tempOk = false } // too hot inside + if(extTempHigh) { retval = false; externalTempOk = false } + if(intTemp > desiredTemp+insideThresh) { retval = false; internalTempOk = false } // too hot inside } if(modeHeat || oldMode == "heat" || (!canCool && canHeat)) { str = "less than" - if(extTempLow) { retval = false; tempOk = false } - else if (intTemp < desiredTemp-insideThresh) { retval = false; tempOk = false } // too cold inside + if(extTempLow) { retval = false; externalTempOk = false } + if(intTemp < desiredTemp-insideThresh) { retval = false; internalTempOk = false } // too cold inside } LogAction("extTmpTempOk: extTempHigh: ${extTempHigh} | extTempLow: ${extTempLow}", "debug", false) } } def showRes = disp ? (retval != last ? true : false) : false if(!dpOk) { - LogAction("extTmpTempOk: ${retval} Dewpoint: (${curDp}°${getTemperatureScale()}) is ${dpOk ? "ok" : "TOO HIGH"}", "info", showRes) + LogAction("extTmpTempOk: ${retval} Dewpoint: (${curDp}${tUnitStr()}) is ${dpOk ? "ok" : "TOO HIGH"}", "info", showRes) } else { if(!modeAuto) { - LogAction("extTmpTempOk: ${retval} Desired Inside Temp: (${desiredTemp}°${getTemperatureScale()}) is ${tempOk ? "" : "Not"} ${str} $diffThresh° of Outside Temp: (${extTemp}°${getTemperatureScale()}) or Inside Temp: (${intTemp}) is ${tempOk ? "" : "Not"} within Inside Threshold: ${insideThresh} of desired (${desiredTemp})", "info", showRes) + LogAction("extTmpTempOk: ${retval} Desired Inside Temp: (${desiredTemp}${tUnitStr()}) is ${externalTempOk ? "" : "Not"} ${str} $diffThresh\u00b0 of Outside Temp: (${extTemp}${tUnitStr()}) ${retval ? "AND" : "OR"} Inside Temp: (${intTemp}) is ${internalTempOk ? "" : "Not"} within Inside Threshold: ${insideThresh} of desired (${desiredTemp})", "info", showRes) } else { - LogAction("extTmpTempOk: ${retval} Exterior Temperature (${extTemp}°${getTemperatureScale()}) is ${tempOk ? "" : "Not"} ${str} using $diffThresh° offset | Inside Temp: (${intTemp})", "info", showRes) + LogAction("extTmpTempOk: ${retval} Exterior Temperature (${extTemp}${tUnitStr()}) is ${externalTempOk ? "" : "Not"} ${str} using $diffThresh\u00b0 offset | Inside Temp: (${intTemp}${tUnitStr()})", "info", showRes) } } @@ -3207,19 +3353,21 @@ def extTmpTempCheck(cTimeOut = false) { def execTime = now() //atomicState?.lastEvalDt = getDtNow() - if(!atomicState?."${pName}timeOutOn") { atomicState."${pName}timeOutOn" = false } + if(atomicState?."${pName}timeOutOn" == null) { atomicState."${pName}timeOutOn" = false } if(cTimeOut) { atomicState."${pName}timeOutOn" = true } def timeOut = atomicState."${pName}timeOutOn" ?: false - def curMode = extTmpTstat?.currentnestThermostatMode?.toString() - def modeOff = (curMode in ["off", "eco"]) ? true : false + def curMode = extTmpTstat ? extTmpTstat?.currentnestThermostatMode?.toString() : null + def modeOff = (curMode in ["off"]) ? true : false + def modeInActive = (curMode in ["off", "eco"]) ? true : false def modeEco = (curMode in ["eco"]) ? true : false + def modeAuto = (curMode == "auto") ? true : false def allowNotif = settings?."${pName}NotificationsOn" ? true : false def allowSpeech = allowNotif && settings?."${pName}AllowSpeechNotif" ? true : false def allowAlarm = allowNotif && settings?."${pName}AllowAlarmNotif" ? true : false def speakOnRestore = allowSpeech && settings?."${pName}SpeechOnRestore" ? true : false - if(!modeOff) { atomicState."${pName}timeOutOn" = false; timeOut = false } + if(!modeInActive) { atomicState."${pName}timeOutOn" = false; timeOut = false } // if we requested off; and someone switched us on or nMode took over... if( atomicState?.extTmpTstatOffRequested && (!modeEco || (modeEco && parent.setNModeActive(null))) ) { // reset timer and states LogAction("extTmpTempCheck: | ${!modeEco ? "HVAC turned on when automation had OFF" : "Automation overridden by nMODE"}, resetting state to match", "warn", true) @@ -3231,14 +3379,30 @@ def extTmpTempCheck(cTimeOut = false) { unschedTimeoutRestore(pName) } + if(modeOff) { + storeExecutionHistory((now() - execTime), "extTmpTempCheck") + return + } + def mylastMode = atomicState?."${pName}lastMode" // when we state change that could change desired Temp ensure delays happen before off can happen again def lastDesired = atomicState?.extTmpLastDesiredTemp // this catches scheduled temp or hvac mode changes def desiredTemp = getDesiredTemp() if( (mylastMode != curMode) || (desiredTemp && desiredTemp != lastDesired)) { - if(!modeOff) { + if(!modeInActive) { atomicState?."${pName}lastMode" = curMode +//ERS if(desiredTemp) { atomicState?.extTmpLastDesiredTemp = desiredTemp } + def desiredHeatTemp + def desiredCoolTemp + if(modeAuto) { + desiredHeatTemp = getRemSenHeatSetTemp(curMode) + desiredCoolTemp = getRemSenCoolSetTemp(curMode) + if(desiredHeatTemp && desiredCoolTemp) { + atomicState?.extTmpLastDesiredHTemp = desiredHeatTemp + atomicState?.extTmpLastDesiredCTemp = desiredCoolTemp + } + } atomicState.extTmpChgWhileOnDt = getDtNow() } else { //atomicState.extTmpChgWhileOffDt = getDtNow() @@ -3261,7 +3425,7 @@ def extTmpTempCheck(cTimeOut = false) { if(!lastMode) { lastMode = atomicState?.extTmpRestoreMode } } if(lastMode && (lastMode != curMode || timeOut || !safetyOk || !schedOk)) { - scheduleAutomationEval(60) + scheduleAutomationEval(70) if(setTstatMode(extTmpTstat, lastMode, pName)) { storeLastAction("Restored Mode ($lastMode)", getDtNow(), pName, extTmpTstat) atomicState?.extTmpRestoreMode = null @@ -3320,7 +3484,7 @@ def extTmpTempCheck(cTimeOut = false) { } } } else { - if(modeOff) { + if(modeInActive) { if(timeout || !safetyOk) { LogAction("extTmpTempCheck: | Timeout or Safety temps exceeded and Unable to restore settings okToRestore is false", "warn", true) atomicState."${pName}timeOutOn" = false @@ -3337,7 +3501,7 @@ def extTmpTempCheck(cTimeOut = false) { if(tempWithinThreshold && !timeOut && safetyOk && schedOk && !modeEco) { def rmsg = "" - if(!modeOff) { + if(!modeInActive) { if(getExtTmpWhileOnDtSec() >= (getExtTmpOffDelayVal() - 2)) { atomicState."${pName}timeOutOn" = false atomicState?.extTmpRestoreMode = curMode @@ -3348,7 +3512,7 @@ def extTmpTempCheck(cTimeOut = false) { atomicState?.extTmpTstatOffRequested = true atomicState.extTmpChgWhileOffDt = getDtNow() scheduleTimeoutRestore(pName) - modeOff = true + modeInActive = true modeEco = true rmsg = "${extTmpTstat.label} turned 'ECO': External Temp is at the temp threshold for (${getEnumValue(longTimeSecEnum(), extTmpOffDelay)})" if(extTmpTstatMir) { @@ -3398,6 +3562,14 @@ def extTmpGenericEvt(evt) { def extTmpDpOrTempEvt(type) { if(atomicState?.disableAutomation) { return } else { + def extTmpTstat = settings?.schMotTstat + def curMode = extTmpTstat ? extTmpTstat?.currentnestThermostatMode?.toString() : null + def modeOff = (curMode in ["off"]) ? true : false + if(modeOff) { + LogAction("${type} | Thermostat is off HVAC mode: ${curMode}", "info", false) + return + } + atomicState.needWeathUpd = true if(settings?.extTmpUseWeather) { getExtConditions() } @@ -3407,14 +3579,14 @@ def extTmpDpOrTempEvt(type) { if(lastTempWithinThreshold == null || tempWithinThreshold != lastTempWithinThreshold) { - def extTmpTstat = settings?.schMotTstat - def curMode = extTmpTstat?.currentnestThermostatMode.toString() - def modeOff = (curMode in ["off", "eco"]) ? true : false + //def extTmpTstat = settings?.schMotTstat + //def curMode = extTmpTstat ? extTmpTstat?.currentnestThermostatMode?.toString() : null + def modeActive = !(curMode in ["off", "eco"]) ? true : false def offVal = getExtTmpOffDelayVal() def onVal = getExtTmpOnDelayVal() def timeVal - if(!modeOff) { + if(modeActive) { atomicState.extTmpChgWhileOnDt = getDtNow() timeVal = ["valNum":offVal, "valLabel":getEnumValue(longTimeSecEnum(), offVal)] } else { @@ -3431,7 +3603,7 @@ def extTmpDpOrTempEvt(type) { } /****************************************************************************** -| WATCH CONTACTS AUTOMATION CODE | +| WATCH CONTACTS AUTOMATION CODE | *******************************************************************************/ def conWatPrefix() { return "conWat" } @@ -3454,7 +3626,8 @@ def conWatContactDesc() { str += "Contact Status:" settings?.conWatContacts?.sort { it?.displayName }?.each { dev -> cnt = cnt+1 - def val = strCapitalize(dev?.currentContact) ?: "Not Set" + def t0 = strCapitalize(dev?.currentContact) + def val = t0 ?: "Not Set" str += "${(cnt >= 1) ? "${(cnt == cCnt) ? "\n└" : "\n├"}" : "\n└"} ${dev?.label}: (${val})" } return str @@ -3463,7 +3636,7 @@ def conWatContactDesc() { } def isConWatConfigured() { - return (settings?.conWatContacts && settings?.conWatOffDelay) ? true : false + return (settings?.schMotContactOff && settings?.conWatContacts && settings?.conWatOffDelay) ? true : false } def getConWatContactsOk() { return settings?.conWatContacts?.currentState("contact")?.value.contains("open") ? false : true } @@ -3496,14 +3669,13 @@ def conWatCheck(cTimeOut = false) { def execTime = now() //atomicState?.lastEvalDt = getDtNow() - if(!atomicState?."${pName}timeOutOn") { atomicState."${pName}timeOutOn" = false } + if(atomicState?."${pName}timeOutOn" == null) { atomicState."${pName}timeOutOn" = false } if(cTimeOut) { atomicState."${pName}timeOutOn" = true } def timeOut = atomicState."${pName}timeOutOn" ?: false def curMode = conWatTstat ? conWatTstat?.currentnestThermostatMode.toString() : null def modeEco = (curMode in ["eco"]) ? true : false //def curNestPres = getTstatPresence(conWatTstat) def modeOff = (curMode in ["off", "eco"]) ? true : false - def openCtDesc = getOpenContacts(conWatContacts) ? " '${getOpenContacts(conWatContacts)?.join(", ")}' " : " a selected contact " def allowNotif = settings?."${pName}NotificationsOn" ? true : false def allowSpeech = allowNotif && settings?."${pName}AllowSpeechNotif" ? true : false def allowAlarm = allowNotif && settings?."${pName}AllowAlarmNotif" ? true : false @@ -3544,7 +3716,7 @@ def conWatCheck(cTimeOut = false) { if(!lastMode) { lastMode = atomicState?.conWatRestoreMode } } if(lastMode && (lastMode != curMode || timeOut || !safetyOk || !schedOk)) { - scheduleAutomationEval(60) + scheduleAutomationEval(70) if(setTstatMode(conWatTstat, lastMode, pName)) { storeLastAction("Restored Mode ($lastMode) to $conWatTstat", getDtNow(), pName, conWatTstat) atomicState?.conWatRestoreMode = null @@ -3624,8 +3796,10 @@ def conWatCheck(cTimeOut = false) { if((getConWatOpenDtSec() >= (getConWatOffDelayVal() - 2)) && (getConWatRestoreDelayBetweenDtSec() >= (getConWatRestoreDelayBetweenVal() - 2))) { atomicState."${pName}timeOutOn" = false atomicState?.conWatRestoreMode = curMode + def t0 = getOpenContacts(conWatContacts) + def openCtDesc = t0 ? " '${t0?.join(", ")}' " : " a selected contact " LogAction("conWatCheck: Saving ${conWatTstat?.label} mode (${strCapitalize(atomicState?.conWatRestoreMode)})", "info", true) - LogAction("conWatCheck: ${openCtDesc}${getOpenContacts(conWatContacts).size() > 1 ? "are" : "is"} still Open: Turning 'OFF' '${conWatTstat?.label}'", "debug", true) + LogAction("conWatCheck: ${openCtDesc}${t0?.size() > 1 ? "are" : "is"} still Open: Turning 'OFF' '${conWatTstat?.label}'", "debug", true) scheduleAutomationEval(60) if(setTstatMode(conWatTstat, "eco", pName)) { storeLastAction("Set $conWatTstat to 'ECO'", getDtNow(), pName, conWatTstat) @@ -3683,7 +3857,7 @@ def conWatContactEvt(evt) { if(atomicState?.disableAutomation) { return } else { def conWatTstat = settings?.schMotTstat - def curMode = conWatTstat?.currentnestThermostatMode.toString() + def curMode = conWatTstat ? conWatTstat?.currentnestThermostatMode?.toString() : null def isModeOff = (curMode in ["eco"]) ? true : false def conOpen = (evt?.value == "open") ? true : false def canSched = false @@ -3712,7 +3886,7 @@ def conWatContactEvt(evt) { } /****************************************************************************** -| WATCH FOR LEAKS AUTOMATION LOGIC CODE | +| WATCH FOR LEAKS AUTOMATION LOGIC CODE | ******************************************************************************/ def leakWatPrefix() { return "leakWat" } @@ -3724,7 +3898,8 @@ def leakWatSensorsDesc() { str += "Leak Sensors:" settings?.leakWatSensors?.sort { it?.displayName }?.each { dev -> cnt = cnt+1 - def val = strCapitalize(dev?.currentWater) ?: "Not Set" + def t0 = strCapitalize(dev?.currentWater) + def val = t0 ?: "Not Set" str += "${(cnt >= 1) ? "${(cnt == cCnt) ? "\n└" : "\n├"}" : "\n└"} ${dev?.label}: (${val})" } return str @@ -3733,11 +3908,11 @@ def leakWatSensorsDesc() { } def isLeakWatConfigured() { - return (settings?.leakWatSensors) ? true : false + return (settings?.schMotWaterOff && settings?.leakWatSensors) ? true : false } def getLeakWatSensorsOk() { return settings?.leakWatSensors?.currentState("water")?.value.contains("wet") ? false : true } -def leakWatSensorsOk() { return (!settings?.leakWatSensors) ? false : true } +//def leakWatSensorsOk() { return (!settings?.leakWatSensors) ? false : true } //def leakWatScheduleOk() { return autoScheduleOk(leakWatPrefix()) } // TODO allow override from schedule? @@ -3763,7 +3938,6 @@ def leakWatCheck() { def curMode = leakWatTstat?.currentThermostatMode.toString() //def curNestPres = getTstatPresence(leakWatTstat) def modeOff = (curMode == "off") ? true : false - def wetCtDesc = getWetWaterSensors(leakWatSensors) ? " '${getWetWaterSensors(leakWatSensors)?.join(", ")}' " : " a selected leak sensor " def allowNotif = settings?."${pName}NotificationsOn" ? true : false def allowSpeech = allowNotif && settings?."${pName}AllowSpeechNotif" ? true : false def allowAlarm = allowNotif && settings?."${pName}AllowAlarmNotif" ? true : false @@ -3789,7 +3963,7 @@ def leakWatCheck() { def lastMode = null if(atomicState?.leakWatRestoreMode) { lastMode = atomicState?.leakWatRestoreMode } if(lastMode && (lastMode != curMode || !safetyOk)) { - scheduleAutomationEval(60) + scheduleAutomationEval(70) if(setTstatMode(leakWatTstat, lastMode, pName)) { storeLastAction("Restored Mode ($lastMode) to $leakWatTstat", getDtNow(), pName, leakWatTstat) atomicState?.leakWatTstatOffRequested = false @@ -3858,8 +4032,10 @@ def leakWatCheck() { def rmsg = "" if(!modeOff) { atomicState?.leakWatRestoreMode = curMode + def t0 = getWetWaterSensors(leakWatSensors) + def wetCtDesc = t0 ? " '${t0?.join(", ")}' " : " a selected leak sensor " LogAction("leakWatCheck: Saving ${leakWatTstat?.label} mode (${strCapitalize(atomicState?.leakWatRestoreMode)})", "info", true) - LogAction("leakWatCheck: ${wetCtDesc}${getWetWaterSensors(leakWatSensors).size() > 1 ? "are" : "is"} Wet: Turning 'OFF' '${leakWatTstat?.label}'", "debug", true) + LogAction("leakWatCheck: ${wetCtDesc}${t0?.size() > 1 ? "are" : "is"} Wet: Turning 'OFF' '${leakWatTstat?.label}'", "debug", true) scheduleAutomationEval(60) if(setTstatMode(leakWatTstat, "off", pName)) { storeLastAction("Turned Off $leakWatTstat", getDtNow(), pName, leakWatTstat) @@ -3930,7 +4106,7 @@ def leakWatSensorEvt(evt) { } /******************************************************************************** -| MODE AUTOMATION CODE | +| MODE AUTOMATION CODE | *********************************************************************************/ def nModePrefix() { return "nMode" } @@ -3986,7 +4162,7 @@ def nestModePresPage() { input (name: "nModeCamOffHome", type: "bool", title: "Turn Off Nest Cams when Home?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("camera_gray_icon.png")) if(settings?.nModeCamOffHome || settings?.nModeCamOnAway) { paragraph title: "Optional" , "You can choose which cameras are changed when Home/Away. If you don't select any devices all will be changed." - input (name: "nModeCamsSel", type: "device.nestCamera", title: "Select your Nest Cams?", required: false, multiple: true, submitOnChange: true, image: getAppImg("camera_blue_icon.png")) + input (name: "nModeCamsSel", type: "capability.soundSensor", title: "Select your Nest Cams?", required: false, multiple: true, submitOnChange: true, image: getAppImg("camera_blue_icon.png")) } } } @@ -3994,7 +4170,7 @@ def nestModePresPage() { section("Additional Settings:") { input (name: "nModeSetEco", type: "bool", title: "Set ECO mode when away?", required: false, defaultValue: false, submitOnChange: true, image: getDevImg("eco_icon.png")) input (name: "nModeDelay", type: "bool", title: "Delay Changes?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("delay_time_icon.png")) - if(nModeDelay) { + if(settings?.nModeDelay) { input "nModeDelayVal", "enum", title: "Delay before change?", required: false, defaultValue: 60, metadata: [values:longTimeSecEnum()], submitOnChange: true, image: getAppImg("configure_icon.png") } @@ -4004,10 +4180,11 @@ def nestModePresPage() { section(getDmtSectionDesc(nModePrefix())) { def pageDesc = getDayModeTimeDesc(pName) href "setDayModeTimePage", title: "Configured Restrictions", description: pageDesc, params: ["pName": "${pName}"], state: (pageDesc ? "complete" : null), - image: getAppImg("cal_filter_icon.png") + image: getAppImg("cal_filter_icon.png") } section("Notifications:") { - def pageDesc = getNotifConfigDesc(pName) + def t0 = getNotifConfigDesc(pName) + def pageDesc = t0 ? "${t0}\n\nTap to modify" : "" href "setNotificationPage", title: "Configured Alerts", description: pageDesc, params: ["pName":"${pName}", "allowSpeech":false, "allowAlarm":false, "showSchedule":true], state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") } @@ -4020,25 +4197,25 @@ def nestModePresPage() { } } -def nModePresenceDesc() { +String nModePresenceDesc() { if(settings?.nModePresSensor) { - def cCnt = nModePresSensor?.size() ?: 0 - def str = "" - def cnt = 0 + Integer cCnt = settings?.nModePresSensor?.size() ?: 0 + String str = "" + Integer cnt = 0 str += "Presence Status:" settings?.nModePresSensor?.sort { it?.displayName }?.each { dev -> cnt = cnt+1 - def presState = strCapitalize(dev?.currentPresence) ?: "No State" - str += "${(cnt >= 1) ? "${(cnt == cCnt) ? "\n└" : "\n├"}" : "\n└"} ${dev?.label}: ${(dev?.label?.toString()?.length() > 10) ? "\n${(cCnt == 1 || cnt == cCnt) ? " " : "│"}└ " : ""}(${presState})" + String t0 = strCapitalize(dev?.currentPresence) + String presState = t0 ?: "No State" + str += "${(cnt >= 1) ? "${(cnt == cCnt) ? "\n└" : "\n├"}" : "\n└"} ${dev?.label}: ${(dev?.label?.toString()?.length() > 10) ? "\n${(cCnt == 1 || cnt == cCnt) ? " " : " │"} └ " : ""}(${presState})" } return str } return null } -def isNestModesConfigured() { - def devOk = ((!nModePresSensor && !nModeSwitch && (nModeHomeModes && nModeAwayModes)) || (nModePresSensor && !nModeSwitch) || (!nModePresSensor && nModeSwitch)) ? true : false - return devOk +Boolean isNestModesConfigured() { + return ((!settings?.nModePresSensor && !settings?.nModeSwitch && (settings?.nModeHomeModes && settings?.nModeAwayModes)) || (settings?.nModePresSensor && !settings?.nModeSwitch) || (!settings?.nModePresSensor && settings?.nModeSwitch)) } def nModeGenericEvt(evt) { @@ -4047,10 +4224,10 @@ def nModeGenericEvt(evt) { LogAction("${evt?.name.toUpperCase()} Event | Device: ${evt?.displayName} | Value: (${strCapitalize(evt?.value)}) with a delay of ${eventDelay}ms", "trace", true) if(atomicState?.disableAutomation) { return } storeLastEventData(evt) - if(nModeDelay) { - def delay = nModeDelayVal.toInteger() ?: 60 + if(settings?.nModeDelay) { + Integer delay = settings?.nModeDelayVal.toInteger() ?: 60 if(delay > defaultAutomationTime()) { - LogAction("Event | A Check is scheduled (${getEnumValue(longTimeSecEnum(), nModeDelayVal)})", "info", false) + LogAction("Event | A Check is scheduled (${getEnumValue(longTimeSecEnum(), settings?.nModeDelayVal)})", "info", false) scheduleAutomationEval(delay) } else { scheduleAutomationEval() } } else { @@ -4059,11 +4236,11 @@ def nModeGenericEvt(evt) { } def adjustCameras(on, sendAutoType=null) { - def cams = settings?.nModeCamsSel ?: parent?.getCams() - def foundCams + def cams = parent?.getCams() if(cams) { + def foundCams if(settings?.nModeCamsSel) { - foundCams = cams + foundCams = settings?.nModeCamsSel } else { foundCams = cams?.collect { parent.getCameraDevice(it) } } @@ -4082,7 +4259,7 @@ def adjustCameras(on, sendAutoType=null) { } catch (ex) { log.error "adjustCameras() Exception: ${dev?.label} does not support commands on / off", ex - sendNofificationMsg("Warning", "Camera commands not found, check IDE logs and installation instructions") + sendEventPushNotifications("Camera commands not found, check IDE logs and installation instructions", "Warning", nModePrefix()) parent?.sendExceptionData(ex, "adjustCameras", true, getAutoType()) } return dev @@ -4099,25 +4276,30 @@ def adjustEco(on, senderAutoType=null) { def d1 = parent.getThermostatDevice(dni) if(d1) { def didstr = null + def tstatAction = null def curMode = d1?.currentnestThermostatMode?.toString() - if(on && (curMode in ["eco"])) { - if(senderAutoType) { sendEcoActionDescToDevice(d1, senderAutoType) } // THIS ONLY WORKS ON NEST THERMOSTATS - } + def prevMode = d1?.currentpreviousthermostatMode?.toString() + //LogAction("adjustEco: CURMODE: ${curMode} ON: ${on} PREVMODE: ${prevMode}", "trace", false) + if(on && !(curMode in ["eco", "off"])) { didstr = "ECO" - setTstatMode(d1, "eco", senderAutoType) + tstatAction = "eco" } - def prevMode = d1?.currentpreviousthermostatMode?.toString() - LogAction("adjustEco: CURMODE: ${curMode} ON: ${on} PREVMODE: ${prevMode}", "trace", false) if(!on && curMode in ["eco"]) { if(prevMode && prevMode != curMode) { didstr = "$prevMode" - setTstatMode(d1, prevMode, senderAutoType) + tstatAction = prevMode } } if(didstr) { + setTstatMode(d1, tstatAction, senderAutoType) LogAction("adjustEco($on): | Thermostat: ${d1?.displayName} setting to HVAC mode $didstr was $curMode", "trace", true) storeLastAction("Set ${d1?.displayName} to $didstr", getDtNow(), senderAutoType, d1) + } else { + if(on && (curMode in ["eco"])) { // override device to know nMODE is active + if(senderAutoType) { sendEcoActionDescToDevice(d1, senderAutoType) } // THIS ONLY WORKS ON NEST THERMOSTATS + } + LogAction("adjustEco: | Thermostat: ${d1?.displayName} NOCHANGES CURMODE: ${curMode} ON: ${on} PREVMODE: ${prevMode}", "trace", false) } return d1 } else { LogAction("adjustEco NO D1", "warn", true) } @@ -4155,6 +4337,7 @@ def setAway(away) { } def nModeScheduleOk() { return autoScheduleOk(nModePrefix()) } +def getnModeEvalDtSec() { return !atomicState?.nModelastEvalDt ? 100000 : GetTimeDiffSeconds(atomicState?.nModelastEvalDt, null, "getnModeEvalDtSec").toInteger() } def checkNestMode() { LogAction("checkNestMode", "trace", false) @@ -4184,6 +4367,7 @@ def checkNestMode() { def away = false def home = false +// ERS figure out what state we are in if(nModePresSensor && !nModeSwitch) { if(!isPresenceHome(nModePresSensor)) { away = true @@ -4207,12 +4391,56 @@ def checkNestMode() { LogAction("checkNestMode: Nothing Matched", "info", true) } +// Track changes that happen outside of nMode +// this won't attempt to reset Nest device eco or camera state - you chose to do it outside the automation + Boolean NMisEnabled = parent.automationNestModeEnabled(true) + Boolean NMecoisEnabled = parent.setNModeActive(null) + Boolean t0 = (!nModeSetEco) + Boolean t1 = (home && (!nestModeAway) ) + if( (t0 || t1) && NMecoisEnabled) { + LogAction("checkNestMode adjusting manager state NM is not setting eco", "warn", true) + parent.setNModeActive(false) // clear nMode has it in manager + } + if(t1) { atomicState?.nModeTstatLocAway = false } + def t2 = (away && nestModeAway) ? true : false + if(nModeSetEco && t2 && (!NMecoisEnabled)) { + LogAction("checkNestMode adjusting manager state NM will clear eco", "warn", true) + parent.setNModeActive(true) // set nMode has it in manager + } + if(t2) { atomicState?.nModeTstatLocAway = true } + + def homeChgd = false + def nestModeChgd = false + if(atomicState?.nModeLastHome != home) { + homeChgd = true; + LogAction("NestMode Home Changed: ${homeChgd} Home: ${home}", "info", true) + atomicState.nModeLastHome = home + } + def t5 = getNestLocPres() + if(atomicState?.nModeLastNestMode != t5) { + nestModeChgd = true; + def t6 = "info" + if(!homeChgd) { + t6 = "warn" + } + LogAction("Nest location mode Changed: ${t5}", t6, true) + atomicState.nModeLastNestMode = t5 + } + def didsomething = false +// Manage state changes if(away && !nestModeAway) { - LogAction("checkNestMode: ${awayDesc} Nest 'Away'", "info", true) + LogAction("checkNestMode: ${awayDesc} Nest 'Away' ${away} ${nestModeAway}", "info", true) + if(getnModeEvalDtSec() < 4*60) { + LogAction("checkNestMode did change recently - SKIPPING", "warn", true) + scheduleAutomationEval(90) + storeExecutionHistory((now() - execTime), "checkNestMode") + return + } didsomething = true setAway(true) + atomicState.nModeLastNestMode = "away" atomicState?.nModeTstatLocAway = true if(nModeSetEco) { parent.setNModeActive(true) // set nMode has it in manager @@ -4224,10 +4452,17 @@ def checkNestMode() { if(nModeCamOnAway) { adjustCameras(true, pName) } } else if(home && nestModeAway) { - LogAction("checkNestMode: ${homeDesc} Nest 'Home'", "info", true) + LogAction("checkNestMode: ${homeDesc} Nest 'Home' ${home} ${nestModeAway}", "info", true) + if(getnModeEvalDtSec() < 4*60) { + LogAction("checkNestMode did change recently - SKIPPING", "warn", true) + scheduleAutomationEval(90) + storeExecutionHistory((now() - execTime), "checkNestMode") + return + } didsomething = true setAway(false) parent.setNModeActive(false) // clear nMode has it in manager + atomicState.nModeLastNestMode = "home" atomicState?.nModeTstatLocAway = false if(nModeSetEco) { adjustEco(false, pName) } if(allowNotif) { @@ -4239,6 +4474,7 @@ def checkNestMode() { LogAction("checkNestMode: No Changes | ${nModePresSensor ? "isPresenceHome: ${isPresenceHome(nModePresSensor)} | " : ""}ST-Mode: ($curStMode) | NestModeAway: ($nestModeAway) | Away: ($away) | Home: ($home)", "info", false) } if(didsomething) { + atomicState?.nModelastEvalDt = getDtNow() scheduleAutomationEval(90) } storeExecutionHistory((now() - execTime), "checkNestMode") @@ -4431,7 +4667,9 @@ def getCurrentSchedule() { } if(ccnt > schedList?.size()) { noSched = true } else { mySched = ccnt } - LogTrace("getCurrentSchedule: mySched: $mySched noSched: $noSched ccnt: $ccnt res1: $res1") + if(mySched != null) { + LogTrace("getCurrentSchedule: mySched: $mySched noSched: $noSched ccnt: $ccnt res1: $res1") + } return mySched } @@ -4692,7 +4930,7 @@ def checkOnMotion(mySched) { LogAction("checkOnMotion: [ActiveDt: ${lastActiveMotionDt} (${lastActiveMotionSec} sec) | InActiveDt: ${lastInactiveMotionDt} (${lastInactiveMotionSec} sec) | MotionOn: ($motionOn)", "trace", false) - def ontimedelay = (settings."${sLbl}MDelayValOn"?.toInteger() ?: 60) * 1000 // default to 60s + def ontimedelay = (settings."${sLbl}MDelayValOn"?.toInteger() ?: 60) * 1000 // default to 60s def offtimedelay = (settings."${sLbl}MDelayValOff"?.toInteger() ?: 30*60) * 1000 // default to 30 min def ontimeNum = lastActiveMotionDt + ontimedelay @@ -4895,7 +5133,7 @@ def setTstatTempCheck() { } /******************************************************************************** -| MASTER AUTOMATION FOR THERMOSTATS | +| MASTER AUTOMATION FOR THERMOSTATS | *********************************************************************************/ def schMotPrefix() { return "schMot" } @@ -4908,7 +5146,7 @@ def schMotModePage() { def dupTstat3 def tStatPhys def tempScale = getTemperatureScale() - def tempScaleStr = "°${tempScale}" + def tempScaleStr = "${tUnitStr()}" section("Configure Thermostat") { input name: "schMotTstat", type: "capability.thermostat", title: "Select Thermostat?", multiple: false, submitOnChange: true, required: true, image: getAppImg("thermostat_icon.png") //log.debug "schMotTstat: ${schMotTstat}" @@ -4927,11 +5165,11 @@ def schMotModePage() { def tempSrcStr = (getCurrentSchedule() && atomicState?.remoteTempSourceStr == "Schedule") ? "Schedule ${getCurrentSchedule()} (${"${getSchedLbl(getCurrentSchedule())}" ?: "Not Found"})" : "(${atomicState?.remoteTempSourceStr})" str += tempSrcStr ? "Zone Status:\n• Temp Source:${tempSrcStr?.toString().length() > 15 ? "\n └" : ""} ${tempSrcStr}" : "" - str += curZoneTemp ? "\n• Temperature: (${curZoneTemp}°${getTemperatureScale()})" : "" + str += curZoneTemp ? "\n• Temperature: (${curZoneTemp}${tempScaleStr})" : "" - def hstr = canHeat ? "H: ${reqSenHeatSetPoint}°${getTemperatureScale()}" : "" + def hstr = canHeat ? "H: ${reqSenHeatSetPoint}${tempScaleStr}" : "" def cstr = canHeat && canCool ? "/" : "" - cstr += canCool ? "C: ${reqSenCoolSetPoint}°${getTemperatureScale()}" : "" + cstr += canCool ? "C: ${reqSenCoolSetPoint}${tempScaleStr}" : "" str += "\n• Setpoints: (${hstr}${cstr})\n" str += "\nThermostat Status:\n• Temperature: (${getDeviceTemp(tstat)}${tempScaleStr})" @@ -4944,7 +5182,7 @@ def schMotModePage() { str += (atomicState?.schMotTstatHasFan) ? "\n• FanMode: (${strCapitalize(tstat?.currentThermostatFanMode)})" : "\n• No Fan on HVAC system" str += "\n• Presence: (${strCapitalize(getTstatPresence(tstat))})" def safetyTemps = getSafetyTemps(tstat) - str += safetyTemps ? "\n• Safety Temps:\n └ Min: ${safetyTemps.min}°${getTemperatureScale()}/Max: ${safetyTemps.max}${tempScaleStr}" : "" + str += safetyTemps ? "\n• Safety Temps:\n └ Min: ${safetyTemps.min}${tempScaleStr}/Max: ${safetyTemps.max}${tempScaleStr}" : "" str += "\n• Virtual: (${tstat?.currentNestType.toString() == "virtual" ? "True" : "False"})" paragraph "${str}", title: "${tstat.displayName} Zone Status", state: (str != "" ? "complete" : null), image: getAppImg("info_icon2.png") @@ -4954,7 +5192,7 @@ def schMotModePage() { if(dupTstat1) { paragraph "ERROR:\nThe Virtual version of the Primary Thermostat was found in Mirror Thermostat List.\nPlease Correct to Proceed", required: true, state: null, image: getAppImg("error_icon.png") } - } else { // if physcial thermostat, see if virtual version is in mirror list + } else { // if physcial thermostat, see if virtual version is in mirror list def mylist = [ deviceNetworkId:"v${tstat.deviceNetworkId.toString()}" ] dupTstat2 = checkThermostatDupe(mylist, tstatMir) if(dupTstat2) { @@ -5028,7 +5266,7 @@ def schMotModePage() { section("Remote Sensor:") { if(tStatPhys || settings?.schMotRemoteSensor) { def desc = "" - input (name: "schMotRemoteSensor", type: "bool", title: "Use Alternate Temp Sensors Control Zone temperature?", description: desc, required: false, defaultValue: false, submitOnChange: true, + input (name: "schMotRemoteSensor", type: "bool", title: "Use Alternate Temp Sensors to Control Zone temperature?", description: desc, required: false, defaultValue: false, submitOnChange: true, image: getAppImg("remote_sensor_icon.png")) if(settings?.schMotRemoteSensor) { def remSenDescStr = "" @@ -5058,6 +5296,12 @@ def schMotModePage() { def remSenDesc = isRemSenConfigured() ? "${remSenDescStr}\n\nTap to modify" : null href "tstatConfigAutoPage", title: "Remote Sensor Config", description: remSenDesc ?: "Not Configured", params: ["configType":"remSen"], required: true, state: (remSenDesc ? "complete" : null), image: getAppImg("configure_icon.png") + } else { + if(settings?.vthermostat != null) { +//ERS + settingRemove("vthermostat") + removeVstat("automation Selection") + } } } else if(!tStatPhys) { paragraph "Remote Sensor is not available on a VIRTUAL Thermostat", state: "complete", image: getAppImg("info_icon2.png") } @@ -5084,7 +5328,7 @@ def schMotModePage() { leakDesc += (settings?.leakWatSensors) ? "\n\nTap to modify" : "" def leakWatDesc = isLeakWatConfigured() ? "${leakDesc}" : null href "tstatConfigAutoPage", title: "Leak Sensor Automation", description: leakWatDesc ?: "Tap to configure", params: ["configType":"leakWat"], required: true, state: (leakWatDesc ? "complete" : null), - image: getAppImg("configure_icon.png") + image: getAppImg("configure_icon.png") } } else if(!tStatPhys) { paragraph "Leak Detection is not available on a VIRTUAL Thermostat", state: "complete", image: getAppImg("info_icon2.png") @@ -5110,7 +5354,7 @@ def schMotModePage() { conDesc += (settings?.conWatContacts) ? "\n\nTap to modify" : "" def conWatDesc = isConWatConfigured() ? "${conDesc}" : null href "tstatConfigAutoPage", title: "Contact Sensors Config", description: conWatDesc ?: "Tap to configure", params: ["configType":"conWat"], required: true, state: (conWatDesc ? "complete" : null), - image: getAppImg("configure_icon.png") + image: getAppImg("configure_icon.png") } } else if(!tStatPhys) { paragraph "Contact automation is not available on a VIRTUAL Thermostat", state: "complete", image: getAppImg("info_icon2.png") @@ -5134,7 +5378,7 @@ def schMotModePage() { humDesc += ((settings?.humCtrlTempSensor || settings?.humCtrlUseWeather) ) ? "\n\nTap to modify" : "" def humCtrlDesc = isHumCtrlConfigured() ? "${humDesc}" : null href "tstatConfigAutoPage", title: "Humidifier Config", description: humCtrlDesc ?: "Tap to configure", params: ["configType":"humCtrl"], required: true, state: (humCtrlDesc ? "complete" : null), - image: getAppImg("configure_icon.png") + image: getAppImg("configure_icon.png") } } section("External Temp:") { @@ -5158,7 +5402,7 @@ def schMotModePage() { extDesc += ((settings?.extTmpTempSensor || settings?.extTmpUseWeather) ) ? "\n\nTap to modify" : "" def extTmpDesc = isExtTmpConfigured() ? "${extDesc}" : null href "tstatConfigAutoPage", title: "External Temps Config", description: extTmpDesc ?: "Tap to configure", params: ["configType":"extTmp"], required: true, state: (extTmpDesc ? "complete" : null), - image: getAppImg("configure_icon.png") + image: getAppImg("configure_icon.png") } } else if(!tStatPhys) { paragraph "External Temp automation is not available on a VIRTUAL Thermostat", state: "complete", image: getAppImg("info_icon2.png") @@ -5260,7 +5504,7 @@ def tstatConfigAutoPage(params) { def tstat = settings?.schMotTstat if (tstat) { def tempScale = getTemperatureScale() - def tempScaleStr = "°${tempScale}" + def tempScaleStr = "${tUnitStr()}" def tStatName = tstat?.displayName.toString() def tStatHeatSp = getTstatSetpoint(tstat, "heat") def tStatCoolSp = getTstatSetpoint(tstat, "cool") @@ -5288,7 +5532,7 @@ def tstatConfigAutoPage(params) { section { def str = "" str += "• Temperature: (${tStatTemp})" - str += "\n• Setpoints: (H: ${canHeat ? "${tStatHeatSp}${tempScaleStr}" : "NA"}/C: ${canCool ? "${tStatCoolSp}${tempScaleStr}" : "NA"})" // + str += "\n• Setpoints: (H: ${canHeat ? "${tStatHeatSp}${tempScaleStr}" : "NA"}/C: ${canCool ? "${tStatCoolSp}${tempScaleStr}" : "NA"})" paragraph title: "${tStatName}\nSchedules and Setpoints:", "${str}", state: "complete", image: getAppImg("info_icon2.png") } showUpdateSchedule(null, hidestr) @@ -5342,7 +5586,7 @@ def tstatConfigAutoPage(params) { section(getDmtSectionDesc(fanCtrlPrefix())) { def pageDesc = getDayModeTimeDesc(pName) href "setDayModeTimePage", title: "Configured Restrictions", description: pageDesc, params: ["pName": "${pName}"], state: (pageDesc ? "complete" : null), - image: getAppImg("cal_filter_icon.png") + image: getAppImg("cal_filter_icon.png") } if(settings?."${pName}FanSwitches") { @@ -5364,13 +5608,11 @@ def tstatConfigAutoPage(params) { if(!getMyLockId()) { setMyLockId(app.id) } +//ERS +// this deals with changing the tstat on the automation if(atomicState?.remSenTstat) { if(tstat.deviceNetworkId != atomicState?.remSenTstat) { - parent?.addRemoveVthermostat(atomicState.remSenTstat, false, getMyLockId()) - if( parent?.remSenUnlock(atomicState.remSenTstat, getMyLockId()) ) { // attempt unlock old ID - atomicState.oldremSenTstat = atomicState?.remSenTstat - atomicState?.remSenTstat = null - } + removeVstat("settings pages") } } if(settings?.schMotRemoteSensor) { @@ -5381,13 +5623,11 @@ def tstatConfigAutoPage(params) { } if(configType == "remSen") { - // can check if any vthermostat is owned by us, and delete it - // have issue request for vthermostat is still on as input below - if(cannotLock) { section("") { paragraph "Cannot Lock thermostat for remote sensor - thermostat may already be in use. Please Correct", required: true, state: null, image: getAppImg("error_icon.png") } + settingRemove("vthermostat") } if(!cannotLock) { @@ -5477,9 +5717,10 @@ def tstatConfigAutoPage(params) { image: getAppImg("delay_time_icon.png") } section("Notifications:") { - def pageDesc = getNotifConfigDesc(pName) + def t0 = getNotifConfigDesc(pName) + def pageDesc = t0 ? "${t0}\n\nTap to modify" : "" href "setNotificationPage", title: "Configured Alerts", description: pageDesc, params: ["pName":"${pName}", "allowSpeech":true, "allowAlarm":true, "showSchedule":true], - state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") + state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") } } } @@ -5514,12 +5755,13 @@ def tstatConfigAutoPage(params) { section(getDmtSectionDesc(conWatPrefix())) { def pageDesc = getDayModeTimeDesc(pName) href "setDayModeTimePage", title: "Configured Restrictions", description: pageDesc, params: ["pName": "${pName}"], state: (pageDesc ? "complete" : null), - image: getAppImg("cal_filter_icon.png") + image: getAppImg("cal_filter_icon.png") } section("Notifications:") { - def pageDesc = getNotifConfigDesc(pName) + def t0 = getNotifConfigDesc(pName) + def pageDesc = t0 ? "${t0}\n\nTap to modify" : "" href "setNotificationPage", title: "Configured Alerts", description: pageDesc, params: ["pName":"${pName}", "allowSpeech":true, "allowAlarm":true, "showSchedule":true], - state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") + state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") } } } @@ -5601,7 +5843,7 @@ this does not work... section(getDmtSectionDesc(humCtrlPrefix())) { def pageDesc = getDayModeTimeDesc(pName) href "setDayModeTimePage", title: "Configured Restrictions", description: pageDesc, params: ["pName": "${pName}"], state: (pageDesc ? "complete" : null), - image: getAppImg("cal_filter_icon.png") + image: getAppImg("cal_filter_icon.png") } } } @@ -5657,12 +5899,13 @@ this does not work... section(getDmtSectionDesc(extTmpPrefix())) { def pageDesc = getDayModeTimeDesc(pName) href "setDayModeTimePage", title: "Configured Restrictions", description: pageDesc, params: ["pName": "${pName}"], state: (pageDesc ? "complete" : null), - image: getAppImg("cal_filter_icon.png") + image: getAppImg("cal_filter_icon.png") } section("Notifications:") { - def pageDesc = getNotifConfigDesc(pName) + def t0 = getNotifConfigDesc(pName) + def pageDesc = t0 ? "${t0}\n\nTap to modify" : "" href "setNotificationPage", title: "Configured Alerts", description: pageDesc, params: ["pName":"${pName}", "allowSpeech":true, "allowAlarm":true, "showSchedule":true], - state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") + state: (pageDesc ? "complete" : null), image: getAppImg("notification_icon.png") } def schTitle if(!atomicState?.activeSchedData?.size()) { @@ -5698,18 +5941,19 @@ def scheduleConfigPage(params) { def reqSenCoolSetPoint = getRemSenCoolSetTemp() def curZoneTemp = getRemoteSenTemp() def tempSrcStr = atomicState?.remoteTempSourceStr + def tempScaleStr = "${tUnitStr()}" section { - str += "Zone Status:\n• Temp Source: (${tempSrcStr})\n• Temperature: (${curZoneTemp}°${getTemperatureScale()})" + str += "Zone Status:\n• Temp Source: (${tempSrcStr})\n• Temperature: (${curZoneTemp}${tempScaleStr})" - def hstr = canHeat ? "H: ${reqSenHeatSetPoint}°${getTemperatureScale()}" : "" + def hstr = canHeat ? "H: ${reqSenHeatSetPoint}${tempScaleStr}" : "" def cstr = canHeat && canCool ? "/" : "" - cstr += canCool ? "C: ${reqSenCoolSetPoint}°${getTemperatureScale()}" : "" + cstr += canCool ? "C: ${reqSenCoolSetPoint}${tempScaleStr}" : "" str += "\n• Setpoints: (${hstr}${cstr})\n" - str += "\nThermostat Status:\n• Temperature: (${getDeviceTemp(tstat)}°${getTemperatureScale()})" - hstr = canHeat ? "H: ${getTstatSetpoint(tstat, "heat")}°${getTemperatureScale()}" : "" + str += "\nThermostat Status:\n• Temperature: (${getDeviceTemp(tstat)}${tempScaleStr})" + hstr = canHeat ? "H: ${getTstatSetpoint(tstat, "heat")}${tempScaleStr}" : "" cstr = canHeat && canCool ? "/" : "" - cstr += canCool ? "C: ${getTstatSetpoint(tstat, "cool")}°${getTemperatureScale()}" : "" + cstr += canCool ? "C: ${getTstatSetpoint(tstat, "cool")}${tempScaleStr}" : "" str += "\n• Setpoints: (${hstr}${cstr})" str += "\n• Mode: (${tstat ? ("${strCapitalize(tstat?.currentThermostatOperatingState)}/${strCapitalize(tstat?.currentThermostatMode)}") : "unknown"})" @@ -5739,9 +5983,9 @@ def schMotSchedulePage(params) { } def getScheduleList() { - def cnt = parent ? parent?.state?.appData?.schedules?.count : null - def maxCnt = cnt ? cnt.toInteger() : 4 - maxCnt = Math.min( Math.max(cnt,4), 8) + def cnt = parent ? parent?.state?.appData?.settings?.schedules?.count : null + def maxCnt = cnt ? cnt.toInteger() : 8 + maxCnt = Math.min( Math.max(maxCnt,4), 8) if(maxCnt < atomicState?.lastScheduleList?.size()) { maxCnt = atomicState?.lastScheduleList?.size() LogAction("A schedule size issue has occurred. The configured schedule size is smaller than the previous configuration restoring previous schedule size.", "warn", true) @@ -5785,7 +6029,7 @@ def editSchedule(schedData) { def sLbl = "schMot_${cnt}_" def canHeat = atomicState?.schMotTstatCanHeat def canCool = atomicState?.schMotTstatCanCool - def tempScaleStr = "°${getTemperatureScale()}" + def tempScaleStr = "${tUnitStr()}" def act = settings["${sLbl}SchedActive"] def actIcon = act ? "active" : "inactive" def sectStr = schedData?.secData?.schName ? (act ? "Enabled" : "Disabled") : "Tap to Enable" @@ -5878,7 +6122,7 @@ def getScheduleDesc(num = null) { def result = [:] def schedData = atomicState?.activeSchedData def actSchedNum = getCurrentSchedule() - def tempScaleStr = "°${getTemperatureScale()}" + def tempScaleStr = "${tUnitStr()}" def schNum def schData @@ -5945,15 +6189,15 @@ def getScheduleDesc(num = null) { str += schData?.p1 ? "\n │ ${(schData?.p0 || isSw) ? "│" : " "} └ (${schData?.p1.size()} Selected)" : "" str += schData?.p0 ? "\n │ ${isSw ? "├" : "└"} Presence Away:${!isSomebodyHome(settings["${sLbl}restrictionPresAway"]) ? " (${okSym()})" : " (${notOkSym()})"}" : "" //str += schData?.p0 ? "$p0Str" : "" - str += schData?.p0 ? "\n │ ${isSw ? "│" : " "} └ (${schData?.p0.size()} Selected)" : "" + str += schData?.p0 ? "\n │ ${isSw ? "│" : " "} └ (${schData?.p0.size()} Selected)" : "" str += schData?.s1 ? "\n │ ${schData?.s0 ? "├" : "└"} Switches On:${isSwitchOn(settings["${sLbl}restrictionSwitchOn"]) ? " (${okSym()})" : " (${notOkSym()})"}" : "" str += schData?.s1 ? "\n │ ${schData?.s0 ? "│" : " "} └ (${schData?.s1.size()} Selected)" : "" str += schData?.s0 ? "\n │ └ Switches Off:${!isSwitchOn(settings["${sLbl}restrictionSwitchOff"]) ? " (${okSym()})" : " (${notOkSym()})"}" : "" - str += schData?.s0 ? "\n │ └ (${schData?.s0.size()} Selected)" : "" + str += schData?.s0 ? "\n │ └ (${schData?.s0.size()} Selected)" : "" //Temp Setpoints - str += isTemp ? "${isRestrict ? "\n │\n" : "\n"} ${(isMot || isRemSen) ? "├" : "└"} Temp Setpoints:" : "" + str += isTemp ? "${isRestrict ? "\n │\n" : "\n"} ${(isMot || isRemSen) ? "├" : "└"} Temp Setpoints:" : "" str += schData?.ctemp ? "\n ${tempPreBar} ${schData?.htemp ? "├" : "└"} Cool Setpoint: (${fixTempSetting(schData?.ctemp)}${tempScaleStr})" : "" str += schData?.htemp ? "\n ${tempPreBar} ${schData?.hvacm ? "├" : "└"} Heat Setpoint: (${fixTempSetting(schData?.htemp)}${tempScaleStr})" : "" str += schData?.hvacm ? "\n ${tempPreBar} └ HVAC Mode: (${strCapitalize(schData?.hvacm)})" : "" @@ -5967,23 +6211,23 @@ def getScheduleDesc(num = null) { // m0dSize = m0dSize+1 // } str += isMot ? "${isTemp || isFanEn || isRemSen || isRestrict ? "\n │\n" : "\n"} ${isRemSen ? "├" : "└"} Motion Settings:" : "" - str += isMot ? "\n ${motPreBar ? "│" : " "} ${(schData?.mctemp || schData?.mhtemp) ? "├" : "└"} Motion Sensors: (${schData?.m0.size()})" : "" + str += isMot ? "\n ${motPreBar ? "│" : " "} ${(schData?.mctemp || schData?.mhtemp) ? "├" : "└"} Motion Sensors: (${schData?.m0.size()})" : "" //str += schData?.m0 ? "$m0Str" : "" //str += isMot ? "\n ${motPreBar ? "│" : " "} ${schData?.mctemp || schData?.mhtemp ? "│" : ""} └ (${isMotionActive(settings["${sLbl}Motion"]) ? "Active" : "None Active"})" : "" - str += isMot && schData?.mctemp ? "\n ${motPreBar ? "│" : " "} ${(schData?.mctemp || schData?.mhtemp) ? "├" : "└"} Mot. Cool Setpoint: (${fixTempSetting(schData?.mctemp)}${tempScaleStr})" : "" - str += isMot && schData?.mhtemp ? "\n ${motPreBar ? "│" : " "} ${schData?.mdelayOn || schData?.mdelayOff ? "├" : "└"} Mot. Heat Setpoint: (${fixTempSetting(schData?.mhtemp)}${tempScaleStr})" : "" - str += isMot && schData?.mhvacm ? "\n ${motPreBar ? "│" : " "} ${(schData?.mdelayOn || schData?.mdelayOff) ? "├" : "└"} Mot. HVAC Mode: (${strCapitalize(schData?.mhvacm)})" : "" - str += isMot && schData?.mdelayOn ? "\n ${motPreBar ? "│" : " "} ${schData?.mdelayOff ? "├" : "└"} Mot. On Delay: (${getEnumValue(longTimeSecEnum(), schData?.mdelayOn)})" : "" - str += isMot && schData?.mdelayOff ? "\n ${motPreBar ? "│" : " "} └ Mot. Off Delay: (${getEnumValue(longTimeSecEnum(), schData?.mdelayOff)})" : "" + str += isMot && schData?.mctemp ? "\n ${motPreBar ? "│" : " "} ${(schData?.mctemp || schData?.mhtemp) ? "├" : "└"} Mot. Cool Setpoint: (${fixTempSetting(schData?.mctemp)}${tempScaleStr})" : "" + str += isMot && schData?.mhtemp ? "\n ${motPreBar ? "│" : " "} ${schData?.mdelayOn || schData?.mdelayOff ? "├" : "└"} Mot. Heat Setpoint: (${fixTempSetting(schData?.mhtemp)}${tempScaleStr})" : "" + str += isMot && schData?.mhvacm ? "\n ${motPreBar ? "│" : " "} ${(schData?.mdelayOn || schData?.mdelayOff) ? "├" : "└"} Mot. HVAC Mode: (${strCapitalize(schData?.mhvacm)})" : "" + str += isMot && schData?.mdelayOn ? "\n ${motPreBar ? "│" : " "} ${schData?.mdelayOff ? "├" : "└"} Mot. On Delay: (${getEnumValue(longTimeSecEnum(), schData?.mdelayOn)})" : "" + str += isMot && schData?.mdelayOff ? "\n ${motPreBar ? "│" : " "} └ Mot. Off Delay: (${getEnumValue(longTimeSecEnum(), schData?.mdelayOff)})" : "" //Remote Sensor Info str += isRemSen && schData?.sen0 ? "${isRemSen || isRestrict ? "\n │\n" : "\n"} └ Alternate Remote Sensor:" : "" - //str += isRemSen && schData?.sen0 ? "\n ├ Temp Sensors: (${schData?.sen0.size()})" : "" + //str += isRemSen && schData?.sen0 ? "\n ├ Temp Sensors: (${schData?.sen0.size()})" : "" settings["${sLbl}remSensor"]?.each { t -> - str += "\n ├ ${t?.label}: ${(t?.label?.toString()?.length() > 10) ? "\n │ └ " : ""}(${getDeviceTemp(t)}°${getTemperatureScale()})" + str += "\n ├ ${t?.label}: ${(t?.label?.toString()?.length() > 10) ? "\n │ └ " : ""}(${getDeviceTemp(t)}${tempScaleStr})" } - str += isRemSen && schData?.sen0 ? "\n └ Temp${(settings["${sLbl}remSensor"]?.size() > 1) ? " (avg):" : ":"} (${getDeviceTempAvg(settings["${sLbl}remSensor"])}${tempScaleStr})" : "" - str += isRemSen && schData?.thres ? "\n └ Threshold: (${settings["${sLbl}remSenThreshold"]}${tempScaleStr})" : "" + str += isRemSen && schData?.sen0 ? "\n └ Temp${(settings["${sLbl}remSensor"]?.size() > 1) ? " (avg):" : ":"} (${getDeviceTempAvg(settings["${sLbl}remSensor"])}${tempScaleStr})" : "" + str += isRemSen && schData?.thres ? "\n └ Threshold: (${settings["${sLbl}remSenThreshold"]}${tempScaleStr})" : "" //log.debug "str: \n$str" if(str != "") { result[schNum] = str } } @@ -6077,7 +6321,7 @@ def roundTemp(Double temp) { if(temp == null) { return null } def newtemp if( getTemperatureScale() == "C") { - newtemp = Math.round(temp.round(1) * 2) / 2.0f // + newtemp = Math.round(temp.round(1) * 2) / 2.0f } else { if(temp instanceof Integer) { //log.debug "roundTemp: ($temp) is Integer" @@ -6289,14 +6533,12 @@ def storeExecutionHistory(val, method = null) { def addToList(val, list, listSize) { if(list?.size() < listSize) { list.push(val) - } - else if(list?.size() > listSize) { + } else if(list?.size() > listSize) { def nSz = (list?.size()-listSize) + 1 def nList = list?.drop(nSz) nList?.push(val) list = nList - } - else if(list?.size() == listSize) { + } else if(list?.size() == listSize) { def nList = list?.drop(1) nList?.push(val) list = nList @@ -6320,7 +6562,7 @@ def getAverageValue(items) { *************************************************************************************************/ def setNotificationPage(params) { - def pName = params.pName + def pName = params?.pName def allowSpeech = false def allowAlarm = false def showSched = false @@ -6332,48 +6574,92 @@ def setNotificationPage(params) { } dynamicPage(name: "setNotificationPage", title: "Configure Notification Options", uninstall: false) { section("Notification Preferences:") { - input "${pName}NotificationsOn", "bool", title: "Enable Notifications?", description: (!settings["${pName}NotificationsOn"] ? "Enable Text, Voice, Ask Alexa, or Alarm Notifications" : ""), required: false, defaultValue: false, submitOnChange: true, - image: getAppImg("notification_icon.png") + input "${pName}NotificationsOn", "bool", title: "Enable Notifications?", description: (!settings["${pName}NotificationsOn"] ? "Enable Text, Voice, Ask Alexa, or Alarm Notifications" : ""), required: false, + defaultValue: false, submitOnChange: true, image: getAppImg("notification_icon.png") } + def fixSettings = false if(settings["${pName}NotificationsOn"]) { - def notifDesc = !location.contactBookEnabled ? "Enable Push Messages Below" : "(Manager App Recipients are used by default)" - section("${notifDesc}") { - if(!location.contactBookEnabled) { + section("Use NST Manager Settings:") { + input "${pName}UseMgrNotif", "bool", title: "Use Manager Settings?", defaultValue: true, submitOnChange: true, required: false, image: getAppImg("notification_icon2.png") + } + if(!settings?."${pName}UseMgrNotif") { + + section("Enable Text Messaging:") { + input "${pName}NotifPhones", "phone", title: "Send SMS to\n(Optional)", submitOnChange: true, required: false, image: getAppImg("notification_icon2.png") + } + section("Enable Push Messages:") { input "${pName}UsePush", "bool", title: "Send Push Notitifications\n(Optional)", required: false, submitOnChange: true, defaultValue: false, image: getAppImg("notification_icon.png") - } else { - input("${pName}NotifRecips", "contact", title: "Select Recipients\n(Optional)", required: false, multiple: true, submitOnChange: true, image: getAppImg("recipient_icon.png")) { - input ("${pName}NotifPhones", "phone", title: "Phone Number to Send SMS to\n(Optional)", submitOnChange: true, required: false) + } + section("Enable Pushover Support:") { + input "${pName}PushoverEnabled", "bool", title: "Use Pushover Integration", required: false, submitOnChange: true, image: getAppImg("pushover_icon.png") + if(settings?."${pName}PushoverEnabled" == true) { + if(atomicState?.isInstalled) { + if(!atomicState?.pushoverManager) { + paragraph "If this is the first time enabling Pushover than leave this page and come back if the devices list is empty" + pushover_init() + } else { + input "${pName}PushoverDevices", "enum", title: "Select Pushover Devices", description: "Tap to select", groupedOptions: getPushoverDevices(), multiple: true, required: true, submitOnChange: true + if(settings?."${pName}PushoverDevices") { + def t0 = [(-2):"Lowest", (-1):"Low", 0:"Normal", 1:"High", 2:"Emergency"] + input "${pName}PushoverPriority", "enum", title: "Notification Priority (Optional)", description: "Tap to select", defaultValue: 0, required: false, multiple: false, submitOnChange: true, options: t0 + input "${pName}PushoverSound", "enum", title: "Notification Sound (Optional)", description: "Tap to select", defaultValue: "pushover", required: false, multiple: false, submitOnChange: true, options: getPushoverSounds() + } + } + } else { paragraph "New Install Detected!!!\n\nPlease complete the NST Automation Install. Then return later to resume Pushover configuration.", state: "complete" } } } + if(settings?."${pName}NotifPhones" || settings?."${pName}UsePush" || (settings?."${pName}PushoverEnabled" /* && settings?."${pName}PushoverDevices" */)) { + section("Notification Restrictions:") { + input "${pName}UseParentNotifRestrictions", "bool", title: "Use Notification Schedule From Manager", required: false, defaultValue: true, submitOnChange: true + if(!settings?."${pName}UseParentNotifRestrictions") { + def t1 = getNotifSchedDesc(pName) + href "setNotificationTimePage", title: "Notification Restrictions", description: (t1 ?: "Tap to configure"), params: ["pName": pName], state: (t1 ? "complete" : null), image: getAppImg("restriction_icon.png") + } + } + } + + } else { + fixSettings = true } + } else { + fixSettings = true + } + if(fixSettings) { + settingRemove("${pName}NotifPhones") + settingRemove("${pName}UsePush") + settingRemove("${pName}PushoverEnabled") + settingRemove("${pName}PushoverDevices") + settingRemove("${pName}PushoverPriority") + settingRemove("${pName}PushoverSound") + settingRemove("${pName}UseParentNotifRestrictions") + settingRemove("${pName}qStartInput") + settingRemove("${pName}qStartTime") + settingRemove("${pName}qStopInput") + settingRemove("${pName}qStopTime") + settingRemove("${pName}quietDays") + settingRemove("${pName}quietModes") + settingRemove("${pName}NotifRecips") + stateRemove("pushoverManager") } if(allowSpeech && settings?."${pName}NotificationsOn") { section("Voice Notification Preferences:") { input "${pName}AllowSpeechNotif", "bool", title: "Enable Voice Notifications?", description: "Media players, Speech Devices, or Ask Alexa", required: false, defaultValue: (settings?."${pName}AllowSpeechNotif" ? true : false), submitOnChange: true, image: getAppImg("speech_icon.png") if(settings["${pName}AllowSpeechNotif"]) { - if(pName == "leakWat") { - if(!atomicState?."${pName}OffVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { atomicState?."${pName}OffVoiceMsg" = "ATTENTION: %devicename% has been turned OFF because %wetsensor% has reported it is WET" } - if(!atomicState?."${pName}OnVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { atomicState?."${pName}OnVoiceMsg" = "Restoring %devicename% to %lastmode% Mode because ALL water sensors have been Dry again for (%ondelay%)" } - } - if(pName == "conWat") { - if(!atomicState?."${pName}OffVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { atomicState?."${pName}OffVoiceMsg" = "ATTENTION: %devicename% has been turned OFF because %opencontact% has been Opened for (%offdelay%)" } - if(!atomicState?."${pName}OnVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { atomicState?."${pName}OnVoiceMsg" = "Restoring %devicename% to %lastmode% Mode because ALL contacts have been Closed again for (%ondelay%)" } - } - if(pName == "extTmp") { - if(!atomicState?."${pName}OffVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { atomicState?."${pName}OffVoiceMsg" = "ATTENTION: %devicename% has been turned to ECO because External Temp is above the temp threshold for (%offdelay%)" } - if(!atomicState?."${pName}OnVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { atomicState?."${pName}OnVoiceMsg" = "Restoring %devicename% to %lastmode% Mode because External Temp has been above the temp threshold for (%ondelay%)" } - } + setInitialVoiceMsgs(pName) input "${pName}SendToAskAlexaQueue", "bool", title: "Send to Ask Alexa Message Queue?", required: false, defaultValue: (settings?."${pName}AllowSpeechNotif" ? false : true), submitOnChange: true, image: askAlexaImgUrl() input "${pName}SpeechMediaPlayer", "capability.musicPlayer", title: "Select Media Player(s)", hideWhenEmpty: true, multiple: true, required: false, submitOnChange: true, image: getAppImg("media_player.png") + input "${pName}EchoDevices", "device.echoSpeaksDevice", title: "Select Alexa Devices(s)", hideWhenEmpty: true, multiple: true, required: false, submitOnChange: true, image: getAppImg('echo_speaks.png') input "${pName}SpeechDevices", "capability.speechSynthesis", title: "Select Speech Synthesizer(s)", hideWhenEmpty: true, multiple: true, required: false, submitOnChange: true, image: getAppImg("speech2_icon.png") - if(settings["${pName}SpeechMediaPlayer"]) { + if(settings["${pName}SpeechMediaPlayer"] || settings["${pName}EchoDevices"]) { input "${pName}SpeechVolumeLevel", "number", title: "Default Volume Level?", required: false, defaultValue: 30, range: "0::100", submitOnChange: true, image: getAppImg("volume_icon.png") - input "${pName}SpeechAllowResume", "bool", title: "Can Resume Playing Media?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("resume_icon.png") + if(settings["${pName}SpeechMediaPlayer"]) { + input "${pName}SpeechAllowResume", "bool", title: "Can Resume Playing Media?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("resume_icon.png") + } } def desc = "" if(pName in ["conWat", "extTmp", "leakWat"]) { - if( (settings["${pName}SpeechMediaPlayer"] || settings["${pName}SpeechDevices"] || settings["${pName}SendToAskAlexaQueue"]) ) { + if( (settings["${pName}SpeechMediaPlayer"] || settings["${pName}SpeechDevices"] || settings["${pName}EchoDevices"] || settings["${pName}SendToAskAlexaQueue"]) ) { switch(pName) { case "conWat": desc = "Contact Close" @@ -6387,7 +6673,7 @@ def setNotificationPage(params) { } input "${pName}SpeechOnRestore", "bool", title: "Speak when restoring HVAC on (${desc})?", required: false, defaultValue: false, submitOnChange: true, image: getAppImg("speech_icon.png") - // TODO There are more messages and errors than ON / OFF + // TODO: There are more messages and errors than ON / OFF input "${pName}UseCustomSpeechNotifMsg", "bool", title: "Customize Notitification Message?", required: false, defaultValue: (settings?."${pName}AllowSpeechNotif" ? false : true), submitOnChange: true, image: getAppImg("speech_icon.png") if(settings["${pName}UseCustomSpeechNotifMsg"]) { @@ -6448,6 +6734,111 @@ def setNotificationPage(params) { } } +def setInitialVoiceMsgs(pName) { + if(settings["${pName}AllowSpeechNotif"]) { + if(pName in ["conWat", "extTmp", "leakWat"]) { + if(pName == "leakWat") { + if(!atomicState?."${pName}OffVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { + atomicState?."${pName}OffVoiceMsg" = "ATTENTION: %devicename% has been turned OFF because %wetsensor% has reported it is WET" } + if(!atomicState?."${pName}OnVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { + atomicState?."${pName}OnVoiceMsg" = "Restoring %devicename% to %lastmode% Mode because ALL water sensors have been Dry again for (%ondelay%)" } + } + if(pName == "conWat") { + if(!atomicState?."${pName}OffVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { + atomicState?."${pName}OffVoiceMsg" = "ATTENTION: %devicename% has been turned OFF because %opencontact% has been Opened for (%offdelay%)" } + if(!atomicState?."${pName}OnVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { + atomicState?."${pName}OnVoiceMsg" = "Restoring %devicename% to %lastmode% Mode because ALL contacts have been Closed again for (%ondelay%)" } + } + if(pName == "extTmp") { + if(!atomicState?."${pName}OffVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { + atomicState?."${pName}OffVoiceMsg" = "ATTENTION: %devicename% has been turned to ECO because External Temp is above the temp threshold for (%offdelay%)" } + if(!atomicState?."${pName}OnVoiceMsg" || !settings["${pName}UseCustomSpeechNotifMsg"]) { + atomicState?."${pName}OnVoiceMsg" = "Restoring %devicename% to %lastmode% Mode because External Temp has been above the temp threshold for (%ondelay%)" } + } + } + } +} + +//ERS +def setCustomVoice(pName) { + if(settings["${pName}AllowSpeechNotif"]) { + if(pName in ["conWat", "extTmp", "leakWat"]) { + if(settings["${pName}UseCustomSpeechNotifMsg"]) { + atomicState?."${pName}OffVoiceMsg" = settings?."${pName}CustomOffSpeechMessage" + atomicState?."${pName}OnVoiceMsg" = settings?."${pName}CustomOnSpeechMessage" + } + } + } +} + +def setNotificationTimePage(params) { + def pName = params?.pName + if(params?.pName) { + atomicState.curNotifTimePageData = params + } else { pName = atomicState?.curNotifTimePageData?.pName } + dynamicPage(name: "setNotificationTimePage", title: "Prevent Notifications\nDuring these Days, Times or Modes", uninstall: false) { + def timeReq = (settings["${pName}qStartTime"] || settings["${pName}qStopTime"]) ? true : false + section() { + input "${pName}qStartInput", "enum", title: "Starting at", options: ["A specific time", "Sunrise", "Sunset"], defaultValue: null, submitOnChange: true, required: false, image: getAppImg("start_time_icon.png") + if(settings["${pName}qStartInput"] == "A specific time") { + input "${pName}qStartTime", "time", title: "Start time", required: timeReq, image: getAppImg("start_time_icon.png") + } + input "${pName}qStopInput", "enum", title: "Stopping at", options: ["A specific time", "Sunrise", "Sunset"], defaultValue: null, submitOnChange: true, required: false, image: getAppImg("stop_time_icon.png") + if(settings?."${pName}qStopInput" == "A specific time") { + input "${pName}qStopTime", "time", title: "Stop time", required: timeReq, image: getAppImg("stop_time_icon.png") + } + input "${pName}quietDays", "enum", title: "Prevent during these days of the week", multiple: true, required: false, image: getAppImg("day_calendar_icon.png"), options: timeDayOfWeekOptions() + input "${pName}quietModes", "mode", title: "Prevent when these Modes are Active", multiple: true, submitOnChange: true, required: false, image: getAppImg("mode_icon.png") + } + } +} + +String getNotifSchedDesc(pName) { + def sun = getSunriseAndSunset() + def startInput = settings?."${pName}qStartInput" + def startTime = settings?."${pName}qStartTime" + def stopInput = settings?."${pName}qStopInput" + def stopTime = settings?."${pName}qStopTime" + def dayInput = settings?."${pName}quietDays" + def modeInput = settings?."${pName}quietModes" + def notifDesc = "" + if(settings?."${pName}UseParentNotifRestrictions" == false) { + def getNotifTimeStartLbl = ( (startInput == "Sunrise" || startInput == "Sunset") ? ( (startInput == "Sunset") ? epochToTime(sun?.sunset.time) : epochToTime(sun?.sunrise.time) ) : (startTime ? time2Str(startTime) : "") ) + def getNotifTimeStopLbl = ( (stopInput == "Sunrise" || stopInput == "Sunset") ? ( (stopInput == "Sunset") ? epochToTime(sun?.sunset.time) : epochToTime(sun?.sunrise.time) ) : (stopTime ? time2Str(stopTime) : "") ) + notifDesc += (getNotifTimeStartLbl && getNotifTimeStopLbl) ? "• Silent Time: ${getNotifTimeStartLbl} - ${getNotifTimeStopLbl}" : "" + def days = getInputToStringDesc(dayInput) + def modes = getInputToStringDesc(modeInput) + notifDesc += days ? "${(getNotifTimeStartLbl || getNotifTimeStopLbl) ? "\n" : ""}• Silent Day${isPluralString(dayInput)}: ${days}" : "" + notifDesc += modes ? "${(getNotifTimeStartLbl || getNotifTimeStopLbl || days) ? "\n" : ""}• Silent Mode${isPluralString(modeInput)}: ${modes}" : "" + } else { + notifDesc += "• Using Manager Restrictions" + } + return (notifDesc != "") ? "${notifDesc}" : null +} + +def getOk2Notify(pName) { + return ((settings["${pName}NotificationsOn"] == true) && (daysOk(settings?."${pName}quietDays") == true) && (notificationTimeOk(pName) == true) && (modesOk(settings?."${pName}quietModes") == true)) +} + +def notificationTimeOk(pName) { + def strtTime = null + def stopTime = null + def now = new Date() + def sun = getSunriseAndSunset() // current based on geofence, previously was: def sun = getSunriseAndSunset(zipCode: zipCode) + if(settings?."${pName}qStartTime" && settings?."${pName}qStopTime") { + if(settings?."${pName}qStartInput" == "sunset") { strtTime = sun.sunset } + else if(settings?."${pName}qStartInput" == "sunrise") { strtTime = sun.sunrise } + else if(settings?."${pName}qStartInput" == "A specific time" && settings?."${pName}qStartTime") { strtTime = settings?."${pName}qStartTime" } + + if(settings?."${pName}qStopInput" == "sunset") { stopTime = sun.sunset } + else if(settings?."${pName}qStopInput" == "sunrise") { stopTime = sun.sunrise } + else if(settings?."${pName}qStopInput" == "A specific time" && settings?."${pName}qStopTime") { stopTime = settings?."${pName}qStopTime" } + } else { return true } + if(strtTime && stopTime) { + return timeOfDayIsBetween(strtTime, stopTime, new Date(), getTimeZone()) ? false : true + } else { return true } +} + def getNotifVariables(pName) { def str = "" str += "\n • DeviceName: %devicename%" @@ -6471,7 +6862,7 @@ def voiceNotifString(phrase, pName) { if(pName == "conWat" && phrase?.toLowerCase().contains("%opencontact%")) { phrase = phrase?.toLowerCase().replace('%opencontact%', (getOpenContacts(conWatContacts) ? getOpenContacts(conWatContacts)?.join(", ").toString() : "a selected contact")) } if(pName == "extTmp" && phrase?.toLowerCase().contains("%tempthreshold%")) { - phrase = phrase?.toLowerCase().replace('%tempthreshold%', "${extTmpDiffVal.toString()}(°${getTemperatureScale()})") } + phrase = phrase?.toLowerCase().replace('%tempthreshold%', "${extTmpDiffVal.toString()}(${tUnitStr()})") } if(phrase?.toLowerCase().contains("%offdelay%")) { phrase = phrase?.toLowerCase().replace('%offdelay%', getEnumValue(longTimeSecEnum(), settings?."${pName}OffDelay").toString()) } if(phrase?.toLowerCase().contains("%ondelay%")) { phrase = phrase?.toLowerCase().replace('%ondelay%', getEnumValue(longTimeSecEnum(), settings?."${pName}OnDelay").toString()) } } catch (ex) { @@ -6481,31 +6872,37 @@ def voiceNotifString(phrase, pName) { return phrase } -def getNotificationOptionsConf(pName) { - LogTrace("getNotificationOptionsConf pName: $pName") - def res = (settings?."${pName}NotificationsOn" && - (getRecipientDesc(pName) || - (settings?."${pName}AllowSpeechNotif" && (settings?."${pName}SpeechDevices" || settings?."${pName}SpeechMediaPlayer")) || - (settings?."${pName}AllowAlarmNofif" && settings?."${pName}AlarmDevices") - ) ) ? true : false - return res -} - def getNotifConfigDesc(pName) { LogTrace("getNotifConfigDesc pName: $pName") def str = "" if(settings?."${pName}NotificationsOn") { - str += ( getRecipientDesc(pName) || (settings?."${pName}AllowSpeechNotif" && (settings?."${pName}SpeechDevices" || settings?."${pName}SpeechMediaPlayer"))) ? - "Notification Status:" : "" - str += (settings?."${pName}NotifRecips") ? "${str != "" ? "\n" : ""} • Contacts: (${settings?."${pName}NotifRecips"?.size()})" : "" - str += (settings?."${pName}UsePush") ? "\n • Push Messages: Enabled" : "" - str += (settings?."${pName}NotifPhones") ? "\n • SMS: (${settings?."${pName}NotifPhones"?.size()})" : "" - def t0 = getVoiceNotifConfigDesc(pName) - str += t0 ? ("${(str != "") ? "\n\n" : "\n"}Voice Status:${t0}") : "" - def t1 = getAlarmNotifConfigDesc(pName) - str += t1 ? ("${(str != "") ? "\n\n" : "\n"}Alarm Status:${t1}") : "" - def t2 = getAlertNotifConfigDesc(pName) - str += t2 ? "\n${t2}" : "" + // str += "Notification Status:" + // if(!getRecipientDesc(pName)) { + // str += "\n • Contacts: Using Manager Settings" + // } + def t0 + if(settings?."${pName}UseMgrNotif" == false) { + str += (settings?."${pName}UsePush") ? "${str != "" ? "\n" : ""} • Push Messages: Enabled" : "" + str += (settings?."${pName}NotifPhones") ? "${str != "" ? "\n" : ""} • SMS: (${settings?."${pName}NotifPhones"?.size()})" : "" + str += (settings?."${pName}PushoverEnabled") ? "${str != "" ? "\n" : ""}Pushover: (Enabled)" : "" + str += (settings?."${pName}PushoverEnabled" && settings?."${pName}PushoverDevices") ? "${str != "" ? "\n" : ""} • Pushover Devices: (${settings?."${pName}PushoverDevices"})" : "" + str += (settings?."${pName}PushoverEnabled" && settings?."${pName}PushoverPriority") ? "${str != "" ? "\n" : ""} • Priority: (${settings?."${pName}PushoverPriority"})" : "" + str += (settings?."${pName}PushoverEnabled" && settings?."${pName}PushoverSound") ? "${str != "" ? "\n" : ""} • Sound: (${settings?."${pName}PushoverSound"})" : "" + t0 = getNotifSchedDesc(pName) + str += t0 ? "\n\nAlert Restrictions:\n${t0}" : "" + } else { + str += " • Enabled Using Manager Settings" + } + t0 = str + if(t0) { + str = "Notification Settings\n${t0}" + } + t0 = getVoiceNotifConfigDesc(pName) + str += t0 ? "\n\nVoice Status:${t0}" : "" + t0 = getAlarmNotifConfigDesc(pName) + str += t0 ? "\n\nAlarm Status:${t0}" : "" + t0 = getAlertNotifConfigDesc(pName) + str += t0 ? "\n\n${t0}" : "" } return (str != "") ? "${str}" : null } @@ -6515,13 +6912,20 @@ def getVoiceNotifConfigDesc(pName) { if(settings?."${pName}NotificationsOn" && settings["${pName}AllowSpeechNotif"]) { def speaks = settings?."${pName}SpeechDevices" def medias = settings?."${pName}SpeechMediaPlayer" + def echos = settings["${pName}EchoDevices"] str += settings["${pName}SendToAskAlexaQueue"] ? "\n• Send to Ask Alexa: (True)" : "" - str += speaks ? "\n• Speech Devices:" : "" + str += speaks ? "\n • Speech Devices:" : "" if(speaks) { def cnt = 1 speaks?.each { str += it ? "\n ${cnt < speaks.size() ? "├" : "└"} $it" : ""; cnt = cnt+1; } } - str += medias ? "${speaks ? "\n\n" : "\n"}• Media Players:" : "" + str += echos ? "\n • Alexa Devices:" : "" + if(echos) { + def cnt = 1 + echos?.each { str += it ? "\n ${cnt < echos.size() ? "├" : "└"} $it" : ""; cnt = cnt+1; } + str += (echos && settings?."${pName}SpeechVolumeLevel") ? "\n└ Volume: (${settings?."${pName}SpeechVolumeLevel"})" : "" + } + str += medias ? "${(speaks || echos) ? "\n\n" : "\n"} • Media Players:" : "" if(medias) { def cnt = 1 medias?.sort { it?.displayName }?.each { str += it ? "\n│${cnt < medias.size() ? "├" : "└"} $it" : ""; cnt = cnt+1; } @@ -6580,10 +6984,9 @@ def isPluralString(obj) { } def getRecipientsNames(val) { - def n = "" - def i = 0 + String n = "" + Integer i = 0 if(val) { - //def valLabel = //log.debug "val: $val" val?.each { r -> i = i + 1 @@ -6594,7 +6997,7 @@ def getRecipientsNames(val) { } def getRecipientDesc(pName) { - return ((settings?."${pName}NotifRecips") || (settings?."${pName}NotifPhones" || settings?."${pName}NotifUsePush")) ? getRecipientsNames(settings?."${pName}NotifRecips") : null + return (settings?."${pName}NotifPhones" || settings?."${pName}NotifUsePush" || (settings?."${pName}PushoverEnabled" && settings?."${pName}PushoverDevices")) ? true : false } def setDayModeTimePage(params) { @@ -6664,7 +7067,7 @@ def getDmtSectionDesc(autoType) { } /************************************************************************************************ -| AUTOMATION SCHEDULE CHECK | +| AUTOMATION SCHEDULE CHECK | *************************************************************************************************/ def autoScheduleOk(autoType) { @@ -6717,44 +7120,69 @@ def autoScheduleOk(autoType) { } /************************************************************************************************ -| SEND NOTIFICATIONS VIA PARENT APP | +| SEND NOTIFICATIONS VIA PARENT APP | *************************************************************************************************/ -def sendNofificationMsg(msg, msgType, recips = null, sms = null, push = null) { - LogAction("sendNofificationMsg($msg, $msgType, $recips, $sms, $push)", "trace", false) - if(recips || sms || push) { - parent?.sendMsg(msgType, msg, true, recips, sms, push) - //LogAction("Send Push Notification to $recips", "info", true) +def sendNofificationMsg(msg, msgType, pName, pushoverMap=null, sms=null, push=null) { + LogAction("sendNofificationMsg($msg, $msgType, $pName, $pushoverMap, $sms, $push)", "trace", false) + if(settings?."${pName}NotificationsOn" == true) { + if(settings?."${pName}UseMgrNotif" == false) { + def ok2Notify = setting?."${pName}UseParentNotifRestrictions" != false ? getOk2Notify(pName) : true //parent?.getOk2Notify() + if(!ok2Notify) { + LogAction("sendMsg: Message Skipped During Quiet Time ($msg)", "info", true) + } else { + def mySms = sms ?: settings?."${pName}NotifPhones" + def myPush = push ?: settings?."${pName}UsePush" + if(mySms || myPush) { + parent?.sendMsg(msgType, msg, true, null, myPhone, myPush) + //LogAction("Send Push Notification to $recips", "info", true) + } + if(settings?."${getAutoType()}PushoverEnabled" && settings?."${getAutoType()}PushoverDevices") { + Map msgObj = [:] + msgObj = pushoverMap ?: [title: msgType, message: msg, priority: (settings?."${getAutoType()}PushoverPriority" ?: 0)] + if(settings?."${getAutoType()}PushoverSound") { msgObj?.sound = settings?."${getAutoType()}PushoverSound" } + parent?.buildPushMessage(settings?."${getAutoType()}PushoverDevices", msgObj, true) + } + } + } else { + parent?.sendMsg(msgType, msg, true) + } } else { - parent?.sendMsg(msgType, msg, true) - } -} - + LogAction("sendMsg: Message Skipped as notifications off ($msg)", "info", true) + } +} + +//PushOver-Manager Input Generation Functions +private getPushoverSounds(){return (Map) atomicState?.pushoverManager?.sounds?:[:]} +private getPushoverDevices(){List opts=[];Map pmd=atomicState?.pushoverManager?:[:];pmd?.apps?.each{k,v->if(v&&v?.devices&&v?.appId){Map dm=[:];v?.devices?.sort{}?.each{i->dm["${i}_${v?.appId}"]=i};addInputGrp(opts,v?.appName,dm);}};return opts;} +private inputOptGrp(List groups,String title){def group=[values:[],order:groups?.size()];group?.title=title?:"";groups<r[v]=v;return r;}} +private addInputGrp(List groups,String title,values){if(values instanceof List){values=listToMap(values)};values.inject(inputOptGrp(groups,title)){r,k,v->return addInputValues(r,k,v)};return groups;} +private addInputGrp(values){addInputGrp([],null,values)} +//PushOver-Manager Location Event Subscription Events, Polling, and Handlers +public pushover_init(){subscribe(location,"pushoverManager",pushover_handler);pushover_poll()} +public pushover_cleanup(){state?.remove("pushoverManager");unsubscribe("pushoverManager");} +public pushover_poll(){sendLocationEvent(name:"pushoverManagerCmd",value:"poll",data:[empty:true],isStateChange:true,descriptionText:"Sending Poll Event to Pushover-Manager")} +public pushover_msg(List devs,Map data){if(devs&&data){sendLocationEvent(name:"pushoverManagerMsg",value:"sendMsg",data:data,isStateChange:true,descriptionText:"Sending Message to Pushover Devices: ${devs}");}} +public pushover_handler(evt){Map pmd=atomicState?.pushoverManager?:[:];switch(evt?.value){case"refresh":def ed = evt?.jsonData;String id = ed?.appId;Map pA = pmd?.apps?.size() ? pmd?.apps : [:];if(id){pA[id]=pA?."${id}"instanceof Map?pA[id]:[:];pA[id]?.devices=ed?.devices?:[];pA[id]?.appName=ed?.appName;pA[id]?.appId=id;pmd?.apps = pA;};pmd?.sounds=ed?.sounds;break;case "reset":pmd=[:];break;};atomicState?.pushoverManager=pmd;} +//Builds Map Message object to send to Pushover Manager +private buildPushMessage(List devices,Map msgData,timeStamp=false){if(!devices||!msgData){return};Map data=[:];data?.appId=app?.getId();data.devices=devices;data?.msgData=msgData;if(timeStamp){data?.msgData?.timeStamp=new Date().getTime()};pushover_msg(devices,data);} /************************************************************************************************ -| GLOBAL Code | Logging AND Diagnostic | +| GLOBAL Code | Logging AND Diagnostic | *************************************************************************************************/ - def sendEventPushNotifications(message, type, pName) { LogTrace("sendEventPushNotifications($message, $type, $pName)") - if(settings["${pName}_Alert_1_Send_Push"] || settings["${pName}_Alert_2_Send_Push"]) { -//TODO this portion is never reached - if(settings["${pName}_Alert_1_CustomPushMessage"]) { - sendNofificationMsg(settings["${pName}_Alert_1_CustomPushMessage"].toString(), type, settings?."${pName}NotifRecips", settings?."${pName}NotifPhones", settings?."${pName}UsePush") - } else { - sendNofificationMsg(message, type, settings?."${pName}NotifRecips", settings?."${pName}NotifPhones", settings?."${pName}UsePush") - } - } else { - sendNofificationMsg(message, type, settings?."${pName}NotifRecips", settings?."${pName}NotifPhones", settings?."${pName}UsePush") - } + sendNofificationMsg(message, type, pName) } def sendEventVoiceNotifications(vMsg, pName, msgId, rmAAMsg=false, rmMsgId) { def allowNotif = settings?."${pName}NotificationsOn" ? true : false def allowSpeech = allowNotif && settings?."${pName}AllowSpeechNotif" ? true : false - def ok2Notify = parent.getOk2Notify() + def ok2Notify = setting?."${pName}UseParentNotifRestrictions" != false ? getOk2Notify(pName) : parent?.getOk2Notify() - LogAction("sendEventVoiceNotifications($vMsg, $pName) ok2Notify: $ok2Notify", "trace", false) + LogAction("sendEventVoiceNotifications($vMsg, $pName) | ok2Notify: $ok2Notify", "trace", false) if(allowNotif && allowSpeech) { - if(ok2Notify && (settings["${pName}SpeechDevices"] || settings["${pName}SpeechMediaPlayer"])) { + if(ok2Notify && (settings["${pName}SpeechDevices"] || settings["${pName}SpeechMediaPlayer"] || settings["${pName}EchoDevices"])) { sendTTS(vMsg, pName) } if(settings["${pName}SendToAskAlexaQueue"]) { // we queue to Alexa regardless of quiet times @@ -6792,11 +7220,10 @@ def removeAskAlexaQueueMsg(msgId, queue=null) { } } - def scheduleAlarmOn(autoType) { LogAction("scheduleAlarmOn: autoType: $autoType a1DelayVal: ${getAlert1DelayVal(autoType)}", "debug", true) def timeVal = getAlert1DelayVal(autoType).toInteger() - def ok2Notify = parent.getOk2Notify() + def ok2Notify = setting?."${autoType}UseParentNotifRestrictions" != false ? getOk2Notify(autoType) : parent?.getOk2Notify() LogAction("scheduleAlarmOn timeVal: $timeVal ok2Notify: $ok2Notify", "info", true) if(canSchedule() && ok2Notify) { @@ -6928,12 +7355,13 @@ def getAlarmEvt2RuntimeDtSec() { return !atomicState?.alarmEvt2StartDt ? 100000 void sendTTS(txt, pName) { LogAction("sendTTS(data: ${txt})", "trace", true) try { - def msg = txt.toString().replaceAll("\\[|\\]|\\(|\\)|\\'|\\_", "") + def msg = txt?.toString()?.replaceAll("\\[|\\]|\\(|\\)|\\'|\\_", "") def spks = settings?."${pName}SpeechDevices" def meds = settings?."${pName}SpeechMediaPlayer" + def echos = settings?."${pName}EchoDevices" def res = settings?."${pName}SpeechAllowResume" def vol = settings?."${pName}SpeechVolumeLevel" - LogAction("sendTTS msg: $msg | speaks: $spks | medias: $meds | resume: $res | volume: $vol", "debug", true) + LogAction("sendTTS msg: $msg | speaks: $spks | medias: $meds | echos: $echos| resume: $res | volume: $vol", "debug", false) if(settings?."${pName}AllowSpeechNotif") { if(spks) { spks*.speak(msg) @@ -6955,6 +7383,9 @@ void sendTTS(txt, pName) { } } } + if(echos) { + echos*.setVolumeAndSpeak(settings?."${pName}SpeechVolumeLevel", msg as String) + } } } catch (ex) { log.error "sendTTS Exception:", ex @@ -7038,7 +7469,8 @@ def checkFanSpeedSupport(dev) { devData.each { cmd -> if(cmd.name in req) { devCnt = devCnt+1 } } - def speed = dev?.currentValue("currentState") ?: null + def t0 = dev?.currentValue("currentState") + def speed = t0 ?: null //log.debug "checkFanSpeedSupport (speed: $speed | devCnt: $devCnt)" return (speed && devCnt == 3) ? true : false } @@ -7113,12 +7545,12 @@ def getSafetyTempsOk(tstat) { } def getGlobalDesiredHeatTemp() { - def t0 = parent?.settings?.locDesiredHeatTemp?.toDouble() + Double t0 = parent?.settings?.locDesiredHeatTemp?.toDouble() return t0 ?: null } def getGlobalDesiredCoolTemp() { - def t0 = parent?.settings?.locDesiredCoolTemp?.toDouble() + Double t0 = parent?.settings?.locDesiredCoolTemp?.toDouble() return t0 ?: null } @@ -7198,7 +7630,7 @@ def getTstatPresence(tstat) { def setTstatMode(tstat, mode, autoType=null) { def result = false - if(mode) { + if(mode && tstat) { def curMode = tstat?.currentnestThermostatMode?.toString() if (curMode != mode) { try { @@ -7216,7 +7648,7 @@ def setTstatMode(tstat, mode, autoType=null) { } catch (ex) { log.error "setTstatMode() Exception: ${tstat?.label} does not support mode ${mode}; check IDE and install instructions", ex - parent?.sendExceptionData(ex, "setTstatMode", true, getAutoType()) + //parent?.sendExceptionData(ex, "setTstatMode", true, getAutoType()) } } @@ -7234,7 +7666,7 @@ def setMultipleTstatMode(tstats, mode, autoType=null) { tstats?.each { ts -> def retval // try { - retval = setTstatMode(ts, mode, autoType) // THERE IS A PROBLEM HERE IF MIRROR THERMOSTATS ARE NOT NEST + retval = setTstatMode(ts, mode, autoType) // } catch (ex) { // log.error "setMultipleTstatMode() Exception:", ex // parent?.sendExceptionData(ex, "setMultipleTstatMode", true, getAutoType()) @@ -7267,10 +7699,11 @@ def setTstatAutoTemps(tstat, coolSetpoint, heatSetpoint, pName, mir=null) { def reqHeat def curCoolSetpoint def curHeatSetpoint + def tempScaleStr = "${tUnitStr()}" if(tstat) { hvacMode = tstat?.currentnestThermostatMode.toString() - LogAction("setTstatAutoTemps: [tstat: ${tstat?.displayName} | Mode: ${hvacMode} | coolSetpoint: ${coolSetpoint}${tUnitStr()} | heatSetpoint: ${heatSetpoint}${tUnitStr()}]", "info", true) + LogAction("setTstatAutoTemps: [tstat: ${tstat?.displayName} | Mode: ${hvacMode} | coolSetpoint: ${coolSetpoint}${tempScaleStr} | heatSetpoint: ${heatSetpoint}${tempScaleStr}]", "info", true) retVal = true setStr = "" @@ -7284,8 +7717,8 @@ def setTstatAutoTemps(tstat, coolSetpoint, heatSetpoint, pName, mir=null) { if(!reqCool && !reqHeat) { retVal = false; setStr += "Missing COOL and HEAT Setpoints" } if(hvacMode in ["auto"]) { - if(!reqCool && reqHeat) { reqCool = (double) (curCoolSetpoint > (reqHeat + diff)) ? curCoolSetpoint : (reqHeat + diff) } - if(!reqHeat && reqCool) { reqHeat = (double) (curHeatSetpoint < (reqCool - diff)) ? curHeatSetpoint : (reqCool - diff) } + if(!reqCool && reqHeat) { reqCool = (double) ((curCoolSetpoint > (reqHeat + diff)) ? curCoolSetpoint : (reqHeat + diff)) } + if(!reqHeat && reqCool) { reqHeat = (double) ((curHeatSetpoint < (reqCool - diff)) ? curHeatSetpoint : (reqCool - diff)) } if((reqCool && reqHeat) && (reqCool >= (reqHeat + diff))) { if(reqHeat <= curHeatSetpoint) { heatFirst = true } else if(reqCool >= curCoolSetpoint) { heatFirst = false } @@ -7316,15 +7749,15 @@ def setTstatAutoTemps(tstat, coolSetpoint, heatSetpoint, pName, mir=null) { } if(retVal) { if(heatFirst && setHeat) { - setStr += "heatSetpoint: (${reqHeat}${tUnitStr()}) " + setStr += "heatSetpoint: (${reqHeat}${tempScaleStr}) " if(reqHeat != curHeatSetpoint) { tstat?.setHeatingSetpoint(reqHeat) - storeLastAction("Set ${tstat} Heat Setpoint ${reqHeat}${tUnitStr()}", getDtNow(), pName, tstat) + storeLastAction("Set ${tstat} Heat Setpoint ${reqHeat}${tempScaleStr}", getDtNow(), pName, tstat) if(mir) { mir*.setHeatingSetpoint(reqHeat) } } } if(setCool) { - setStr += "coolSetpoint: (${reqCool}${tUnitStr()}) " + setStr += "coolSetpoint: (${reqCool}${tempScaleStr}) " if(reqCool != curCoolSetpoint) { tstat?.setCoolingSetpoint(reqCool) storeLastAction("Set ${tstat} Cool Setpoint ${reqCool}", getDtNow(), pName, tstat) @@ -7332,10 +7765,10 @@ def setTstatAutoTemps(tstat, coolSetpoint, heatSetpoint, pName, mir=null) { } } if(!heatFirst && setHeat) { - setStr += "heatSetpoint: (${reqHeat}${tUnitStr()})" + setStr += "heatSetpoint: (${reqHeat}${tempScaleStr})" if(reqHeat != curHeatSetpoint) { tstat?.setHeatingSetpoint(reqHeat) - storeLastAction("Set ${tstat} Heat Setpoint ${reqHeat}${tUnitStr()}", getDtNow(), pName, tstat) + storeLastAction("Set ${tstat} Heat Setpoint ${reqHeat}${tempScaleStr}", getDtNow(), pName, tstat) if(mir) { mir*.setHeatingSetpoint(reqHeat) } } } @@ -7348,7 +7781,7 @@ def setTstatAutoTemps(tstat, coolSetpoint, heatSetpoint, pName, mir=null) { /****************************************************************************** -* Keep These Methods * +* Keep These Methods * *******************************************************************************/ /* def switchEnumVals() { return [0:"Off", 1:"On", 2:"On/Off"] } @@ -7389,8 +7822,8 @@ def shortTimeEnum() { def smallTempEnum() { def tempUnit = getTemperatureScale() def vals = [ - 1:"1°${tempUnit}", 2:"2°${tempUnit}", 3:"3°${tempUnit}", 4:"4°${tempUnit}", 5:"5°${tempUnit}", 6:"6°${tempUnit}", 7:"7°${tempUnit}", - 8:"8°${tempUnit}", 9:"9°${tempUnit}", 10:"10°${tempUnit}" + 1:"1\u00b0${tempUnit}", 2:"2\u00b0${tempUnit}", 3:"3\u00b0${tempUnit}", 4:"4\u00b0${tempUnit}", 5:"5\u00b0${tempUnit}", 6:"6\u00b0${tempUnit}", 7:"7\u00b0${tempUnit}", + 8:"8\u00b0${tempUnit}", 9:"9\u00b0${tempUnit}", 10:"10\u00b0${tempUnit}" ] return vals } @@ -7495,14 +7928,13 @@ def getDevOpt() { def devPageFooter(var, eTime) { def res = [] if(getDevOpt()) { - res += section() { - paragraph " Page Loads: (${atomicState?.usageMetricsStore["${var}"] ?: 0}) | LoadTime: (${eTime ? (now()-eTime) : 0}ms)" + res += section() { + paragraph " Page Loads: (${atomicState?.usageMetricsStore["${var}"] ?: 0}) | LoadTime: (${eTime ? (now()-eTime) : 0}ms)" } } return res?.size() ? res : "" } - def askAlexaImgUrl() { return "https://raw.githubusercontent.com/MichaelStruck/SmartThingsPublic/master/smartapps/michaelstruck/ask-alexa.src/AskAlexa512.png" } def savetoRemDiagChild(List newdata) { @@ -7515,20 +7947,23 @@ def savetoRemDiagChild(List newdata) { } if(newdata?.size() > 0) { def data = atomicState?.remDiagLogDataStore ?: [] + def pdata = atomicState?.remDiagLogpDataStore ?: [] def cnt = 0 - while(data && stateSz >= 70 && cnt < 50) { + while(data && stateSz >= 60 && cnt < 50) { data.remove(0) atomicState?.remDiagLogDataStore = data stateSz = getStateSizePerc() cnt += 1 } newdata?.each { logItem -> + pdata << logItem data << logItem cnt -= 1 //log.debug "item: $logItem" //def item = ["dt":getDtNow(), "type":type, "src":(logSrcType ?: "Not Set"), "msg":msg] } atomicState?.remDiagLogDataStore = data + atomicState?.remDiagLogpDataStore = pdata stateSz = getStateSizePerc() while(data && stateSz >= 75 && cnt < 50) { data.remove(0) @@ -7536,17 +7971,50 @@ def savetoRemDiagChild(List newdata) { stateSz = getStateSizePerc() cnt += 1 } - log.debug "(${data?.size()} | State: ${stateSz}%)" + runIn(6, "displayLogData", [overwrite: true]) + log.debug "Log Items (${data?.size()}) | State Size: (${stateSz}%)" } else { log.error "bad call to savetoRemDiagChild - no data" } } else { Logger("bad call to savetoRemDiagChild - wrong automation") } } +def displayLogData() { + def logData = atomicState?.remDiagLogpDataStore ?: [] + def logSz = logData?.size() ?: 0 + def cnt = 1 + if(logSz > 0) { + logData?.sort { it?.dt }.reverse()?.each { logItem -> + switch(logItem?.type) { + case "info": + log.info "${logItem?.src} ${logItem.msg}" + break + case "warn": + log.warn "${logItem?.src} ${logItem.msg}" + break + case "error": + log.error "${logItem?.src} ${logItem.msg}" + break + case "trace": + log.trace "${logItem?.src} ${logItem.msg}" + break + case "debug": + log.debug "${logItem?.src} ${logItem.msg}" + break + default: + log.debug "${logItem?.src} ${logItem.msg}" + break + } + } + atomicState?.remDiagLogpDataStore = [] + } +} + def getRemLogData() { try { def appHtml = "" def navHtml = "" def scrStr = "" def logData = atomicState?.remDiagLogDataStore + def homeUrl = parent?.getAppEndpointUrl("diagHome") def resultStr = "" def tf = new SimpleDateFormat("h:mm:ss a") tf.setTimeZone(getTimeZone()) @@ -7634,15 +8102,42 @@ def getRemLogData() { - - - - + - +