diff --git a/homie-esp8266-v1-setup-sources/.babelrc b/homie-esp8266-v1-setup-sources/.babelrc
new file mode 100644
index 0000000..11f1df8
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["es2015", "stage-3"]
+}
diff --git a/homie-esp8266-v1-setup-sources/.gitignore b/homie-esp8266-v1-setup-sources/.gitignore
new file mode 100644
index 0000000..580a5df
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/.gitignore
@@ -0,0 +1,5 @@
+/node_modules/
+/public/
+
+/npm-debug.log
+/ui_bundle.gz
diff --git a/homie-esp8266-v1-setup-sources/LICENSE b/homie-esp8266-v1-setup-sources/LICENSE
new file mode 100644
index 0000000..22fbe5d
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/LICENSE
@@ -0,0 +1,339 @@
+GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ {description}
+ Copyright (C) {year} {fullname}
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ {signature of Ty Coon}, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
\ No newline at end of file
diff --git a/homie-esp8266-v1-setup-sources/README.md b/homie-esp8266-v1-setup-sources/README.md
new file mode 100644
index 0000000..2f47e5c
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/README.md
@@ -0,0 +1,11 @@
+Configurator for Homie for ESP8266
+==================================
+
+Sources of the UI to configure an ESP8266 loaded with an Homie firmware.
+
+## Contribute
+
+Contributions are very welcome!
+
+To build assets, just run `npm run dev`.
+This will build the public directory, and watch for changes in the `app` folder.
diff --git a/homie-esp8266-v1-setup-sources/app/assets/favicon.ico b/homie-esp8266-v1-setup-sources/app/assets/favicon.ico
new file mode 100644
index 0000000..24b7795
Binary files /dev/null and b/homie-esp8266-v1-setup-sources/app/assets/favicon.ico differ
diff --git a/homie-esp8266-v1-setup-sources/app/assets/img/favicon-16x16.png b/homie-esp8266-v1-setup-sources/app/assets/img/favicon-16x16.png
new file mode 100644
index 0000000..c0de481
Binary files /dev/null and b/homie-esp8266-v1-setup-sources/app/assets/img/favicon-16x16.png differ
diff --git a/homie-esp8266-v1-setup-sources/app/assets/img/favicon-192x192.png b/homie-esp8266-v1-setup-sources/app/assets/img/favicon-192x192.png
new file mode 100644
index 0000000..3de1566
Binary files /dev/null and b/homie-esp8266-v1-setup-sources/app/assets/img/favicon-192x192.png differ
diff --git a/homie-esp8266-v1-setup-sources/app/assets/img/favicon-32x32.png b/homie-esp8266-v1-setup-sources/app/assets/img/favicon-32x32.png
new file mode 100644
index 0000000..282467e
Binary files /dev/null and b/homie-esp8266-v1-setup-sources/app/assets/img/favicon-32x32.png differ
diff --git a/homie-esp8266-v1-setup-sources/app/assets/img/logo.png b/homie-esp8266-v1-setup-sources/app/assets/img/logo.png
new file mode 100644
index 0000000..72c360d
Binary files /dev/null and b/homie-esp8266-v1-setup-sources/app/assets/img/logo.png differ
diff --git a/homie-esp8266-v1-setup-sources/app/js/app.js b/homie-esp8266-v1-setup-sources/app/js/app.js
new file mode 100644
index 0000000..3c83b4f
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/js/app.js
@@ -0,0 +1,140 @@
+'use strict';
+
+import 'whatwg-fetch';
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+import ConnectionStep from './steps/connection';
+import InfoStep from './steps/info';
+import WifiStep from './steps/wifi';
+import MqttStep from './steps/mqtt';
+import DetailsStep from './steps/details';
+import SendingStep from './steps/sending';
+
+const BASE_API = 'http://homie.config';
+
+const STEP_CONNECTION = 1;
+const STEP_INFO = 2;
+const STEP_WIFI = 3;
+const STEP_MQTT = 4;
+const STEP_DETAILS = 5;
+const STEP_SENDING = 6;
+
+class App extends React.Component {
+ constructor (props) {
+ super(props);
+ this.state = {
+ step: STEP_CONNECTION,
+ name: null,
+ deviceId: null,
+ wifi: { },
+ mqtt: { },
+ ota: { }
+ };
+ }
+
+ nextStep () {
+ this.setState({ step: this.state.step + 1 });
+ }
+
+ setName (name) {
+ this.setState({ name });
+ }
+
+ setDeviceId (deviceId) {
+ this.setState({ deviceId });
+ }
+
+ setWifiCreds (creds) {
+ this.setState({ wifi: creds });
+ }
+
+ setMqttCreds (creds) {
+ this.setState({ mqtt: creds });
+ }
+
+ setOtaCreds (creds) {
+ this.setState({ ota: creds });
+ }
+
+ sendConfig () {
+ let body = {
+ name: this.state.name,
+ wifi: this.state.wifi,
+ mqtt: this.state.mqtt,
+ ota: this.state.ota
+ };
+
+ if (this.state.deviceId !== null) body['device_id'] = this.state.deviceId;
+
+ let options = {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(body)
+ };
+
+ return new Promise((resolve, reject) => {
+ window.fetch(`${BASE_API}/config`, options).then((res) => {
+ return res.json();
+ }).then((json) => {
+ if (json.success) {
+ resolve();
+ } else {
+ reject();
+ }
+ }).catch(() => {
+ reject();
+ });
+ });
+ }
+
+ render () {
+ let Step;
+
+ switch (this.state.step) {
+ case STEP_CONNECTION:
+ Step = ConnectionStep;
+ break;
+ case STEP_INFO:
+ Step = InfoStep;
+ break;
+ case STEP_WIFI:
+ Step = WifiStep;
+ break;
+ case STEP_MQTT:
+ Step = MqttStep;
+ break;
+ case STEP_DETAILS:
+ Step = DetailsStep;
+ break;
+ case STEP_SENDING:
+ Step = SendingStep;
+ break;
+ }
+
+ return (
+
+
Homie for ESP8266
+
Set up your device.
+
+
+
+
this.nextStep()} setWifiCreds={(creds) => this.setWifiCreds(creds)} setMqttCreds={(creds) => this.setMqttCreds(creds)} setName={(name) => this.setName(name)} setDeviceId={(deviceId) => this.setDeviceId(deviceId)} setOtaCreds={(creds) => this.setOtaCreds(creds)} sendConfig={() => this.sendConfig()} />
+
+ );
+ }
+}
+
+ReactDOM.render( , document.getElementById('app'));
diff --git a/homie-esp8266-v1-setup-sources/app/js/steps/connection.js b/homie-esp8266-v1-setup-sources/app/js/steps/connection.js
new file mode 100644
index 0000000..02ff23d
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/js/steps/connection.js
@@ -0,0 +1,53 @@
+'use strict';
+
+import 'whatwg-fetch';
+
+import React from 'react';
+
+export default class ConnectionStep extends React.Component {
+ constructor (props) {
+ super(props);
+ }
+
+ componentDidMount () {
+ let interval;
+ let done = false;
+ let heartbeat = () => {
+ window.fetch(`${this.props.baseApi}/heart`).then((res) => {
+ if (res.ok && !done) {
+ done = true; // prevent multiple request to trigger multiple nextStep
+ window.clearInterval(interval);
+ this.props.nextStep();
+ }
+ });
+ };
+
+ interval = window.setInterval(heartbeat, 5 * 1000);
+ heartbeat();
+ }
+
+ render () {
+ return (
+
+
+
+ Connect to your device Wi-Fi AP.
+ If the AP is named Homie-1234abcd ,
+ the password is 1234abcd .
+
+
+
+ Loading
+ Waiting for the device...
+
+
+ );
+ }
+}
+
+if (process.env.NODE_ENV !== 'production') { // for Preact
+ ConnectionStep.propTypes = {
+ baseApi: React.PropTypes.string.isRequired,
+ nextStep: React.PropTypes.func.isRequired
+ };
+}
diff --git a/homie-esp8266-v1-setup-sources/app/js/steps/details.js b/homie-esp8266-v1-setup-sources/app/js/steps/details.js
new file mode 100644
index 0000000..bf985c0
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/js/steps/details.js
@@ -0,0 +1,144 @@
+'use strict';
+
+import React from 'react';
+
+export default class DetailsStep extends React.Component {
+ constructor (props) {
+ super(props);
+
+ this.state = {
+ ota: false,
+ ssl: false
+ };
+ }
+
+ handleOtaCheckbox (e) {
+ this.setState({ ota: e.target.checked });
+ }
+
+ handleSslCheckbox (e) {
+ this.setState({ ssl: e.target.checked });
+ }
+
+ handleFormSubmit (e) {
+ e.preventDefault();
+
+ let otaCreds = {};
+ otaCreds.enabled = false;
+
+ if (this.state.ota) {
+ otaCreds.enabled = true;
+
+ otaCreds.host = this.refs.host.value;
+ otaCreds.port = parseInt(this.refs.port.value, 10);
+
+ otaCreds.ssl = false;
+ if (this.state.ssl) {
+ otaCreds.ssl = true;
+ if (this.refs.fingerprint.value !== '') otaCreds['fingerprint'] = this.refs.fingerprint.value;
+ }
+
+ otaCreds.path = this.refs.path.value;
+ }
+
+ this.props.setName(this.refs.name.value);
+ if (this.refs.deviceId.value !== '') this.props.setDeviceId(this.refs.deviceId.value);
+ this.props.setOtaCreds(otaCreds);
+
+ this.props.nextStep();
+ }
+
+ render () {
+ return (
+
+
+ A few details before finishing the configuration.
+
+
+
+
+ );
+ }
+}
+
+if (process.env.NODE_ENV !== 'production') { // for Preact
+ DetailsStep.propTypes = {
+ nextStep: React.PropTypes.func.isRequired,
+ mqttConfig: React.PropTypes.object.isRequired,
+ setName: React.PropTypes.func.isRequired,
+ setDeviceId: React.PropTypes.func.isRequired,
+ setOtaCreds: React.PropTypes.func.isRequired
+ };
+}
diff --git a/homie-esp8266-v1-setup-sources/app/js/steps/info.js b/homie-esp8266-v1-setup-sources/app/js/steps/info.js
new file mode 100644
index 0000000..4788011
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/js/steps/info.js
@@ -0,0 +1,105 @@
+'use strict';
+
+import 'whatwg-fetch';
+
+import React from 'react';
+
+export default class InfoStep extends React.Component {
+ constructor (props) {
+ super(props);
+ this.state = {
+ loading: true,
+ info: {}
+ };
+ }
+
+ componentDidMount () {
+ let interval;
+ let done = false;
+ let deviceinfo = () => {
+ window.fetch(`${this.props.baseApi}/device-info`).then((res) => {
+ if (res.ok && !done) {
+ done = true;
+ window.clearInterval(interval);
+ return res.json();
+ }
+ }).then((json) => {
+ this.setState({
+ loading: false,
+ info: json
+ });
+ });
+ };
+
+ interval = window.setInterval(deviceinfo, 5 * 1000);
+ deviceinfo();
+ }
+
+ handleNextButton (e) {
+ e.preventDefault();
+
+ this.props.nextStep();
+ }
+
+ render () {
+ return (
+
+ {(() => {
+ if (this.state.loading) {
+ return (
+
+ Loading
+ Gathering device information...
+
+ );
+ } else {
+ return (
+
+
+ Here are some information about the device you are about to configure:
+
+
+
+ Device ID: { this.state.info.device_id }
+ Homie version: { this.state.info.homie_version }
+ Firmware name: { this.state.info.firmware.name }
+ Firmware version: { this.state.info.firmware.version }
+
+ Nodes:
+
+
+
+ ID
+ Type
+
+
+
+ { this.state.info.nodes.map((node, i) => {
+ return (
+
+ { node.id }
+ { node.type }
+
+ );
+ }) }
+
+
+
+
+
+
{ this.handleNextButton(e); } }>Next
+
+ );
+ }
+ })()}
+
+ );
+ }
+}
+
+if (process.env.NODE_ENV !== 'production') { // for Preact
+ InfoStep.propTypes = {
+ baseApi: React.PropTypes.string.isRequired,
+ nextStep: React.PropTypes.func.isRequired
+ };
+}
diff --git a/homie-esp8266-v1-setup-sources/app/js/steps/mqtt.js b/homie-esp8266-v1-setup-sources/app/js/steps/mqtt.js
new file mode 100644
index 0000000..dda1699
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/js/steps/mqtt.js
@@ -0,0 +1,146 @@
+'use strict';
+
+import React from 'react';
+
+export default class MqttStep extends React.Component {
+ constructor (props) {
+ super(props);
+ this.state = {
+ auth: false,
+ showPassword: false,
+ ssl: false
+ };
+ }
+
+ handleSslCheckbox (e) {
+ this.setState({ ssl: e.target.checked });
+ }
+
+ handleAuthCheckbox (e) {
+ this.setState({ auth: e.target.checked });
+ }
+
+ handleHiddenCheckbox (e) {
+ this.setState({ showPassword: e.target.checked });
+ }
+
+ handleFormSubmit (e) {
+ e.preventDefault();
+
+ let creds = {};
+ creds.host = this.refs.host.value;
+ creds.port = parseInt(this.refs.port.value, 10);
+ if (this.refs.baseTopic.value !== '') creds['base_topic'] = this.refs.baseTopic.value;
+
+ creds.ssl = false;
+ if (this.state.ssl) {
+ creds.ssl = true;
+ if (this.refs.fingerprint.value !== '') creds['fingerprint'] = this.refs.fingerprint.value;
+ }
+
+ creds.auth = false;
+ if (this.state.auth) {
+ creds.auth = true;
+ creds.username = this.refs.username.value;
+ creds.password = this.refs.password.value;
+ }
+
+ this.props.setMqttCreds(creds);
+ this.props.nextStep();
+ }
+
+ render () {
+ return (
+
+
+ Enter the MQTT credentials.
+
+
+
+
+ );
+ }
+}
+
+if (process.env.NODE_ENV !== 'production') { // for Preact
+ MqttStep.propTypes = {
+ nextStep: React.PropTypes.func.isRequired,
+ setMqttCreds: React.PropTypes.func.isRequired
+ };
+}
diff --git a/homie-esp8266-v1-setup-sources/app/js/steps/sending.js b/homie-esp8266-v1-setup-sources/app/js/steps/sending.js
new file mode 100644
index 0000000..4bd41b6
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/js/steps/sending.js
@@ -0,0 +1,58 @@
+'use strict';
+
+import React from 'react';
+
+export default class SendingStep extends React.Component {
+ constructor (props) {
+ super(props);
+ this.state = {
+ loading: true,
+ success: null
+ };
+ }
+
+ componentDidMount () {
+ this.props.sendConfig().then(() => {
+ this.setState({ loading: false, success: true });
+ }).catch(() => {
+ this.setState({ loading: false, success: false });
+ });
+ }
+
+ render () {
+ return (
+
+ {(() => {
+ if (this.state.loading) {
+ return (
+
+ Loading
+ Sending configuration...
+
+ );
+ } else {
+ if (this.state.success) {
+ return (
+
+ The configuration was sent. Your device will reboot.
+
+ );
+ } else {
+ return (
+
+ There was an error while sending the configuration. Please retry.
+
+ );
+ }
+ }
+ })()}
+
+ );
+ }
+}
+
+if (process.env.NODE_ENV !== 'production') { // for Preact
+ SendingStep.propTypes = {
+ sendConfig: React.PropTypes.func.isRequired
+ };
+}
diff --git a/homie-esp8266-v1-setup-sources/app/js/steps/wifi.js b/homie-esp8266-v1-setup-sources/app/js/steps/wifi.js
new file mode 100644
index 0000000..49d12c1
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/js/steps/wifi.js
@@ -0,0 +1,202 @@
+'use strict';
+
+import 'whatwg-fetch';
+
+import React from 'react';
+
+export default class WifiStep extends React.Component {
+ constructor (props) {
+ super(props);
+ this.state = {
+ loading: false,
+ networks: { networks: [] },
+ buttonDisabled: true,
+ selectedSsid: null,
+ showSsidInput: false,
+ showPasswordInput: false,
+ showPassword: false
+ };
+ }
+
+ componentDidMount () {
+ let interval;
+ let done = false;
+ let networks = () => {
+ window.fetch(`${this.props.baseApi}/networks`).then((res) => {
+ if (res.ok && !done) {
+ done = true;
+ window.clearInterval(interval);
+ return res.json();
+ }
+ }).then((json) => {
+ this.setState({
+ loading: false,
+ networks: json
+ });
+ });
+ };
+
+ interval = window.setInterval(networks, 5 * 1000);
+ networks();
+ }
+
+ handleSelectChange (e) {
+ if (e.target.value === 'select') {
+ this.setState({ showSsidInput: false, showPasswordInput: false, selectedSsid: null, buttonDisabled: true });
+ } else if (e.target.value === 'other') {
+ this.setState({ showSsidInput: true, showPasswordInput: true, selectedSsid: null, buttonDisabled: false });
+ } else {
+ let data = e.target.options[e.target.selectedIndex].dataset;
+ this.setState({ showSsidInput: false, showPasswordInput: data.open === 'no', selectedSsid: data.ssid, buttonDisabled: false });
+ }
+ }
+
+ handleHiddenChange (e) {
+ this.setState({ showPassword: e.target.checked });
+ }
+
+ handleFormSubmit (e) {
+ e.preventDefault();
+
+ let creds = {};
+
+ if (this.state.selectedSsid) {
+ creds.ssid = this.state.selectedSsid;
+ } else {
+ creds.ssid = this.refs.ssid.value;
+ }
+ creds.password = this.refs.password.value;
+
+ this.props.setWifiCreds(creds);
+ this.props.nextStep();
+ }
+
+ render () {
+ return (
+
+ {(() => {
+ if (this.state.loading) {
+ return (
+
+ Loading
+ Gathering available networks...
+
+ );
+ } else {
+ this.state.networks.networks.sort(function (networkA, networkB) {
+ if (networkA.rssi > networkB.rssi) {
+ return -1;
+ } else if (networkA.rssi < networkB.rssi) {
+ return 1;
+ } else {
+ return 0;
+ }
+ });
+
+ let networks = this.state.networks.networks.map(function (network) {
+ if (network.rssi <= -100) {
+ network.signalQuality = 0;
+ } else if (network.rssi >= -50) {
+ network.signalQuality = 100;
+ } else {
+ network.signalQuality = 2 * (network.rssi + 100);
+ }
+
+ switch (network.encryption) {
+ case 'wep':
+ network.encryption = 'WEP';
+ break;
+ case 'wpa':
+ network.encryption = 'WPA';
+ break;
+ case 'wpa2':
+ network.encryption = 'WPA2';
+ break;
+ case 'none':
+ network.encryption = 'Open';
+ break;
+ case 'auto':
+ network.encryption = 'Automatic';
+ break;
+ }
+ return network;
+ });
+
+ return (
+
+
+ Select the Wi-Fi network to connect to:
+
+
+
+
+ );
+ }
+ })()}
+
+ );
+ }
+}
+
+if (process.env.NODE_ENV !== 'production') { // for Preact
+ WifiStep.propTypes = {
+ baseApi: React.PropTypes.string.isRequired,
+ nextStep: React.PropTypes.func.isRequired,
+ setWifiCreds: React.PropTypes.func.isRequired
+ };
+}
diff --git a/homie-esp8266-v1-setup-sources/app/vendor/bulma/css/bulma.min.css b/homie-esp8266-v1-setup-sources/app/vendor/bulma/css/bulma.min.css
new file mode 100644
index 0000000..d5d5466
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/vendor/bulma/css/bulma.min.css
@@ -0,0 +1,2 @@
+html,body,body div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,abbr,address,cite,code,del,dfn,em,img,ins,kbd,q,samp,small,strong,sub,sup,var,b,i,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,figure,footer,header,menu,nav,section,time,mark,audio,video,details,summary{margin:0;padding:0;border:0;font-size:100%;font-weight:normal;vertical-align:baseline;background:transparent}article,aside,figure,footer,header,nav,section,details,summary{display:block}html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}img,object,embed{max-width:100%}html{overflow-y:scroll}ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}a{margin:0;padding:0;font-size:100%;vertical-align:baseline;background:transparent}del{text-decoration:line-through}abbr[title],dfn[title]{border-bottom:1px dotted #000;cursor:help}table{border-collapse:collapse;border-spacing:0}th{font-weight:bold;vertical-align:bottom}td{font-weight:normal;vertical-align:top}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}input,select{vertical-align:middle}pre{white-space:pre;white-space:pre-wrap;white-space:pre-line;word-wrap:break-word}input[type="radio"]{vertical-align:text-bottom}input[type="checkbox"]{vertical-align:bottom}select,input,textarea{font:99% sans-serif}table{font-size:inherit;font:100%}small{font-size:85%}strong{font-weight:bold}td,td img{vertical-align:top}sub,sup{font-size:75%;line-height:0;position:relative}sup{top:-0.5em}sub{bottom:-0.25em}pre,code,kbd,samp{font-family:monospace, sans-serif}label,input[type=button],input[type=submit],input[type=file],button{cursor:pointer}button,input,select,textarea{margin:0}button,input[type=button]{width:auto;overflow:visible}@-webkit-keyframes spin-around{from{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin-around{from{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}html{background:#f5f7fa;font-size:14px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:hidden;overflow-y:scroll;text-rendering:optimizeLegibility}html.has-modal-open{overflow:hidden}body,button,input,select,textarea{font-family:"Helvetica Neue","Helvetica","Arial",sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:monospace;line-height:1.25}body{color:#69707a;font-size:1rem;line-height:1.428571428571429}a{color:#1fc8db;cursor:pointer;text-decoration:none;-webkit-transition:none 86ms ease-out;transition:none 86ms ease-out}a:hover{color:#222324}code{background:#f5f7fa;color:#ed6c63;font-size:12px;font-weight:normal;padding:1px 2px 2px}hr{border-top-color:#d3d6db;margin:20px 0}img{max-width:100%}input[type="checkbox"],input[type="radio"]{vertical-align:baseline}small{font-size:11px}strong{color:#222324}article,aside,figure,footer,header,hgroup,section{display:block}pre{background:#f5f7fa;color:#69707a;white-space:pre;word-wrap:normal}pre code{background:#f5f7fa;color:#69707a;display:block;overflow-x:auto;padding:16px 20px}table{width:100%}table th,table td{text-align:left;vertical-align:top}table th{color:#222324}.block:not(:last-child),.content:not(:last-child),.title:not(:last-child),.subtitle:not(:last-child),.message:not(:last-child),.notification:not(:last-child),.progress:not(:last-child),.highlight:not(:last-child),.navbar:not(:last-child),.tabs:not(:last-child),.box:not(:last-child){margin-bottom:20px}.container{position:relative}@media screen and (min-width: 980px){.container{margin:0 auto;max-width:960px}.container.is-fluid{margin:0 20px;max-width:none}}.fa{font-size:21px;text-align:center;vertical-align:top}.content.is-medium{font-size:18px}.content.is-medium code{font-size:14px}.content.is-large{font-size:24px}.content.is-large code{font-size:18px}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#222324;font-weight:300;line-height:1.125;margin-bottom:20px}.content h1:not(:first-child),.content h2:not(:first-child),.content h3:not(:first-child){margin-top:40px}.content h1{font-size:2em}.content h2{font-size:1.75em}.content h3{font-size:1.5em}.content h4{font-size:1.25em}.content h5{font-size:1.125em}.content h6{font-size:1em}.content p:not(:last-child){margin-bottom:1em}.content li+li{margin-top:0.25em}.content ol{list-style:decimal outside;margin:1em 2em}.content ul{list-style:disc outside;margin:1em 2em}.content ul ul{list-style-type:circle;margin-top:0.5em}.content ul ul ul{list-style-type:square}.content blockquote{background:#f5f7fa;border-left:5px solid #d3d6db;padding:1.5em}.content blockquote:not(:last-child){margin-bottom:1em}.highlight{background-color:#fdf6e3;color:#586e75}.highlight .c{color:#93a1a1}.highlight .err,.highlight .g{color:#586e75}.highlight .k{color:#859900}.highlight .l,.highlight .n{color:#586e75}.highlight .o{color:#859900}.highlight .x{color:#cb4b16}.highlight .p{color:#586e75}.highlight .cm{color:#93a1a1}.highlight .cp{color:#859900}.highlight .c1{color:#93a1a1}.highlight .cs{color:#859900}.highlight .gd{color:#2aa198}.highlight .ge{color:#586e75;font-style:italic}.highlight .gr{color:#dc322f}.highlight .gh{color:#cb4b16}.highlight .gi{color:#859900}.highlight .go,.highlight .gp{color:#586e75}.highlight .gs{color:#586e75;font-weight:bold}.highlight .gu{color:#cb4b16}.highlight .gt{color:#586e75}.highlight .kc{color:#cb4b16}.highlight .kd{color:#268bd2}.highlight .kn,.highlight .kp{color:#859900}.highlight .kr{color:#268bd2}.highlight .kt{color:#dc322f}.highlight .ld{color:#586e75}.highlight .m,.highlight .s{color:#2aa198}.highlight .na{color:#B58900}.highlight .nb{color:#586e75}.highlight .nc{color:#268bd2}.highlight .no{color:#cb4b16}.highlight .nd{color:#268bd2}.highlight .ni,.highlight .ne{color:#cb4b16}.highlight .nf{color:#268bd2}.highlight .nl,.highlight .nn,.highlight .nx,.highlight .py{color:#586e75}.highlight .nt,.highlight .nv{color:#268bd2}.highlight .ow{color:#859900}.highlight .w{color:#586e75}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#2aa198}.highlight .sb{color:#93a1a1}.highlight .sc{color:#2aa198}.highlight .sd{color:#586e75}.highlight .s2{color:#2aa198}.highlight .se{color:#cb4b16}.highlight .sh{color:#586e75}.highlight .si,.highlight .sx{color:#2aa198}.highlight .sr{color:#dc322f}.highlight .s1,.highlight .ss{color:#2aa198}.highlight .bp,.highlight .vc,.highlight .vg,.highlight .vi{color:#268bd2}.highlight .il{color:#2aa198}.is-flex{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.is-clearfix:after{clear:both;content:" ";display:table}.is-pulled-left{float:left}.is-pulled-right{float:right}.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}.is-fullwidth{width:100%}.is-text-centered{text-align:center}.is-text-left{text-align:left}.is-text-right{text-align:right}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px){.is-hidden-tablet{display:none !important}}@media screen and (max-width: 979px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 980px){.is-hidden-desktop{display:none !important}}.is-disabled{pointer-events:none}.is-marginless{margin:0 !important}.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.input,.textarea{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;background:#fff;border:1px solid #d3d6db;border-radius:3px;color:#222324;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:14px;height:32px;line-height:24px;padding:3px 8px;position:relative;vertical-align:top;box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);display:block;max-width:100%;width:100%}.input:hover,.textarea:hover{border-color:#aeb1b5}.input:active,.textarea:active,.input:focus,.textarea:focus{border-color:#1fc8db;outline:none}.input[disabled],[disabled].textarea,.input[disabled]:hover,[disabled].textarea:hover{background:#f5f7fa;border-color:#d3d6db;cursor:not-allowed}.input[disabled]::-moz-placeholder,[disabled].textarea::-moz-placeholder,.input[disabled]:hover::-moz-placeholder,[disabled].textarea:hover::-moz-placeholder{color:rgba(34,35,36,0.3)}.input[disabled]::-webkit-input-placeholder,[disabled].textarea::-webkit-input-placeholder,.input[disabled]:hover::-webkit-input-placeholder,[disabled].textarea:hover::-webkit-input-placeholder{color:rgba(34,35,36,0.3)}.input[disabled]:-moz-placeholder,[disabled].textarea:-moz-placeholder,.input[disabled]:hover:-moz-placeholder,[disabled].textarea:hover:-moz-placeholder{color:rgba(34,35,36,0.3)}.input[disabled]:-ms-input-placeholder,[disabled].textarea:-ms-input-placeholder,.input[disabled]:hover:-ms-input-placeholder,[disabled].textarea:hover:-ms-input-placeholder{color:rgba(34,35,36,0.3)}.input.is-dark,.is-dark.textarea{border-color:#222324}.input.is-primary,.is-primary.textarea{border-color:#1fc8db}.input.is-info,.is-info.textarea{border-color:#42afe3}.input.is-success,.is-success.textarea{border-color:#97cd76}.input.is-warning,.is-warning.textarea{border-color:#fce473}.input.is-danger,.is-danger.textarea{border-color:#ed6c63}.input[type="search"],[type="search"].textarea{border-radius:290486px}.input.is-flat,.is-flat.textarea{border:none;box-shadow:none;padding:4px 8px}.input.is-small,.is-small.textarea{border-radius:2px;font-size:11px;height:24px;line-height:16px;padding:3px 6px}.input.is-small.is-flat,.is-small.is-flat.textarea{padding:4px 6px}.input.is-medium,.is-medium.textarea{font-size:18px;height:40px;line-height:32px;padding:3px 10px}.input.is-medium.is-flat,.is-medium.is-flat.textarea{padding:4px 10px}.input.is-large,.is-large.textarea{font-size:24px;height:48px;line-height:40px;padding:3px 12px}.input.is-large.is-flat,.is-large.is-flat.textarea{padding:4px 12px}.input.is-fullwidth,.is-fullwidth.textarea{display:block;width:100%}.input.is-inline,.is-inline.textarea{display:inline;width:auto}.textarea{line-height:1.2;max-height:600px;max-width:100%;min-height:120px;min-width:100%;padding:10px;resize:vertical}.checkbox,.panel-checkbox,.radio{cursor:pointer;display:inline-block;line-height:16px;padding-left:18px;position:relative;vertical-align:top}.checkbox input,.panel-checkbox input,.radio input{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;background:#fff;border:1px solid #d3d6db;border-radius:3px;color:#222324;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:14px;height:32px;line-height:24px;padding:3px 8px;position:relative;vertical-align:top;border-radius:1px;box-shadow:inset 0 1px 1px rgba(0,0,0,0.1);cursor:pointer;float:left;height:14px;left:0;outline:none;padding:0;position:absolute;top:1px;width:14px}.checkbox input:hover,.panel-checkbox input:hover,.radio input:hover{border-color:#aeb1b5}.checkbox input:active,.panel-checkbox input:active,.radio input:active,.checkbox input:focus,.panel-checkbox input:focus,.radio input:focus{border-color:#1fc8db;outline:none}.checkbox input[disabled],.panel-checkbox input[disabled],.radio input[disabled],.checkbox input[disabled]:hover,.panel-checkbox input[disabled]:hover,.radio input[disabled]:hover{background:#f5f7fa;border-color:#d3d6db;cursor:not-allowed}.checkbox input[disabled]::-moz-placeholder,.panel-checkbox input[disabled]::-moz-placeholder,.radio input[disabled]::-moz-placeholder,.checkbox input[disabled]:hover::-moz-placeholder,.panel-checkbox input[disabled]:hover::-moz-placeholder,.radio input[disabled]:hover::-moz-placeholder{color:rgba(34,35,36,0.3)}.checkbox input[disabled]::-webkit-input-placeholder,.panel-checkbox input[disabled]::-webkit-input-placeholder,.radio input[disabled]::-webkit-input-placeholder,.checkbox input[disabled]:hover::-webkit-input-placeholder,.panel-checkbox input[disabled]:hover::-webkit-input-placeholder,.radio input[disabled]:hover::-webkit-input-placeholder{color:rgba(34,35,36,0.3)}.checkbox input[disabled]:-moz-placeholder,.panel-checkbox input[disabled]:-moz-placeholder,.radio input[disabled]:-moz-placeholder,.checkbox input[disabled]:hover:-moz-placeholder,.panel-checkbox input[disabled]:hover:-moz-placeholder,.radio input[disabled]:hover:-moz-placeholder{color:rgba(34,35,36,0.3)}.checkbox input[disabled]:-ms-input-placeholder,.panel-checkbox input[disabled]:-ms-input-placeholder,.radio input[disabled]:-ms-input-placeholder,.checkbox input[disabled]:hover:-ms-input-placeholder,.panel-checkbox input[disabled]:hover:-ms-input-placeholder,.radio input[disabled]:hover:-ms-input-placeholder{color:rgba(34,35,36,0.3)}.checkbox input.is-dark,.panel-checkbox input.is-dark,.radio input.is-dark{border-color:#222324}.checkbox input.is-primary,.panel-checkbox input.is-primary,.radio input.is-primary{border-color:#1fc8db}.checkbox input.is-info,.panel-checkbox input.is-info,.radio input.is-info{border-color:#42afe3}.checkbox input.is-success,.panel-checkbox input.is-success,.radio input.is-success{border-color:#97cd76}.checkbox input.is-warning,.panel-checkbox input.is-warning,.radio input.is-warning{border-color:#fce473}.checkbox input.is-danger,.panel-checkbox input.is-danger,.radio input.is-danger{border-color:#ed6c63}.checkbox input:after,.panel-checkbox input:after,.radio input:after{border:1px solid #fff;border-right:0;border-top:0;content:" ";display:block;height:7px;pointer-events:none;position:absolute;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);width:7px;height:4px;left:3px;opacity:0;position:absolute;top:3px;-webkit-transform:rotate(-45deg) scale(1);transform:rotate(-45deg) scale(1)}.checkbox input:checked,.panel-checkbox input:checked,.radio input:checked{background:#1fc8db;border-color:#1fc8db;box-shadow:none}.checkbox input:checked:after,.panel-checkbox input:checked:after,.radio input:checked:after{opacity:1}.checkbox:hover,.panel-checkbox:hover,.radio:hover{color:#222324}.checkbox:hover input,.panel-checkbox:hover input,.radio:hover input{border-color:#aeb1b5}.checkbox:hover input:checked,.panel-checkbox:hover input:checked,.radio:hover input:checked{border-color:#1fc8db}.is-disabled.checkbox,.is-disabled.panel-checkbox,.is-disabled.radio,.is-disabled.checkbox:hover,.is-disabled.panel-checkbox:hover,.is-disabled.radio:hover{color:#aeb1b5}.radio+.radio{margin-left:10px}.radio input{border-radius:8px}.radio input:after{background:#fff;border:0;border-radius:2px;left:4px;top:4px;-webkit-transform:none;transform:none;width:4px}.select{display:inline-block;height:32px;position:relative;vertical-align:top}.select select{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;background:#fff;border:1px solid #d3d6db;border-radius:3px;color:#222324;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:14px;height:32px;line-height:24px;padding:3px 8px;position:relative;vertical-align:top;cursor:pointer;display:block;outline:none;padding-right:36px}.select select:hover{border-color:#aeb1b5}.select select:active,.select select:focus{border-color:#1fc8db;outline:none}.select select[disabled],.select select[disabled]:hover{background:#f5f7fa;border-color:#d3d6db;cursor:not-allowed}.select select[disabled]::-moz-placeholder,.select select[disabled]:hover::-moz-placeholder{color:rgba(34,35,36,0.3)}.select select[disabled]::-webkit-input-placeholder,.select select[disabled]:hover::-webkit-input-placeholder{color:rgba(34,35,36,0.3)}.select select[disabled]:-moz-placeholder,.select select[disabled]:hover:-moz-placeholder{color:rgba(34,35,36,0.3)}.select select[disabled]:-ms-input-placeholder,.select select[disabled]:hover:-ms-input-placeholder{color:rgba(34,35,36,0.3)}.select select.is-dark{border-color:#222324}.select select.is-primary{border-color:#1fc8db}.select select.is-info{border-color:#42afe3}.select select.is-success{border-color:#97cd76}.select select.is-warning{border-color:#fce473}.select select.is-danger{border-color:#ed6c63}.select select:hover{border-color:#aeb1b5}.select select::ms-expand{display:none}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select:after{border:1px solid #1fc8db;border-right:0;border-top:0;content:" ";display:block;height:7px;pointer-events:none;position:absolute;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);width:7px;margin-top:-6px;right:16px;top:50%}.select:hover:after{border-color:#222324}.label{color:#222324;display:block;font-weight:bold}.label:not(:last-child){margin-bottom:5px}.help{display:block;font-size:11px;margin-top:5px}.help.is-dark{color:#222324}.help.is-primary{color:#1fc8db}.help.is-info{color:#42afe3}.help.is-success{color:#97cd76}.help.is-warning{color:#fce473}.help.is-danger{color:#ed6c63}@media screen and (max-width: 768px){.control-label{margin-bottom:5px}}@media screen and (min-width: 769px){.control-label{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;margin-right:20px;padding-top:7px;text-align:right}}.control{position:relative;text-align:left}.control.is-loading:after{position:absolute !important;right:8px;top:8px}.control:not(:last-child){margin-bottom:10px}.control.has-icon>.fa{display:inline-block;font-size:14px;height:16px;line-height:16px;text-align:center;vertical-align:top;width:16px;color:#aeb1b5;pointer-events:none;position:absolute;top:8px;z-index:4}.control.has-icon .input:focus+.fa,.control.has-icon .textarea:focus+.fa{color:#222324}.control.has-icon:not(.has-icon-right)>.fa{left:8px}.control.has-icon:not(.has-icon-right) .input,.control.has-icon:not(.has-icon-right) .textarea{padding-left:32px}.control.has-icon-right>.fa{right:8px}.control.has-icon-right .input,.control.has-icon-right .textarea{padding-right:32px}.control.has-addons{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.control.has-addons .input,.control.has-addons .textarea,.control.has-addons .button,.control.has-addons .pagination a,.pagination .control.has-addons a,.control.has-addons .select{border-radius:0;margin-right:-1px}.control.has-addons .input:hover,.control.has-addons .textarea:hover,.control.has-addons .button:hover,.control.has-addons .pagination a:hover,.pagination .control.has-addons a:hover,.control.has-addons .select:hover{z-index:2}.control.has-addons .input:active,.control.has-addons .textarea:active,.control.has-addons .input:focus,.control.has-addons .textarea:focus,.control.has-addons .button:active,.control.has-addons .pagination a:active,.pagination .control.has-addons a:active,.control.has-addons .button:focus,.control.has-addons .pagination a:focus,.pagination .control.has-addons a:focus,.control.has-addons .select:active,.control.has-addons .select:focus{z-index:3}.control.has-addons .input:first-child,.control.has-addons .textarea:first-child,.control.has-addons .button:first-child,.control.has-addons .pagination a:first-child,.pagination .control.has-addons a:first-child,.control.has-addons .select:first-child{border-radius:3px 0 0 3px}.control.has-addons .input:first-child select,.control.has-addons .textarea:first-child select,.control.has-addons .button:first-child select,.control.has-addons .pagination a:first-child select,.pagination .control.has-addons a:first-child select,.control.has-addons .select:first-child select{border-radius:3px 0 0 3px}.control.has-addons .input:last-child,.control.has-addons .textarea:last-child,.control.has-addons .button:last-child,.control.has-addons .pagination a:last-child,.pagination .control.has-addons a:last-child,.control.has-addons .select:last-child{border-radius:0 3px 3px 0}.control.has-addons.is-centered{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.control.is-grouped{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.control.is-grouped>.button:not(:last-child),.pagination .control.is-grouped>a:not(:last-child),.control.is-grouped>.input:not(:last-child),.control.is-grouped>.textarea:not(:last-child),.control.is-grouped>.select:not(:last-child){margin-right:10px}.control.is-grouped>.input,.control.is-grouped>.textarea{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}@media screen and (min-width: 769px){.control.is-horizontal{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.control.is-horizontal>.control{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:5;-webkit-flex:5;-ms-flex:5;flex:5}}.button,.pagination a{-moz-appearance:none;-webkit-appearance:none;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;background:#fff;border:1px solid #d3d6db;border-radius:3px;color:#222324;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;font-size:14px;height:32px;line-height:24px;padding:3px 8px;position:relative;vertical-align:top;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding:3px 10px;text-align:center;white-space:nowrap}.button:hover,.pagination a:hover{border-color:#aeb1b5}.button:active,.pagination a:active,.button:focus,.pagination a:focus{border-color:#1fc8db;outline:none}.button[disabled],.pagination a[disabled],.button[disabled]:hover,.pagination a[disabled]:hover{background:#f5f7fa;border-color:#d3d6db;cursor:not-allowed}.button[disabled]::-moz-placeholder,.pagination a[disabled]::-moz-placeholder,.button[disabled]:hover::-moz-placeholder,.pagination a[disabled]:hover::-moz-placeholder{color:rgba(34,35,36,0.3)}.button[disabled]::-webkit-input-placeholder,.pagination a[disabled]::-webkit-input-placeholder,.button[disabled]:hover::-webkit-input-placeholder,.pagination a[disabled]:hover::-webkit-input-placeholder{color:rgba(34,35,36,0.3)}.button[disabled]:-moz-placeholder,.pagination a[disabled]:-moz-placeholder,.button[disabled]:hover:-moz-placeholder,.pagination a[disabled]:hover:-moz-placeholder{color:rgba(34,35,36,0.3)}.button[disabled]:-ms-input-placeholder,.pagination a[disabled]:-ms-input-placeholder,.button[disabled]:hover:-ms-input-placeholder,.pagination a[disabled]:hover:-ms-input-placeholder{color:rgba(34,35,36,0.3)}.button strong,.pagination a strong{color:inherit}.button small,.pagination a small{display:block;font-size:11px;line-height:1;margin-top:5px}.button .icon:first-child,.pagination a .icon:first-child{margin-right:4px}.button .icon:last-child,.pagination a .icon:last-child{margin-left:4px}.button:hover,.pagination a:hover{color:#222324}.button:active,.pagination a:active{box-shadow:inset 0 1px 2px rgba(0,0,0,0.2)}.button.is-dark,.pagination a.is-dark{background:#222324;border-color:transparent;color:#fff}.button.is-dark:hover,.pagination a.is-dark:hover,.button.is-dark:focus,.pagination a.is-dark:focus{background:#090a0a;border-color:transparent;color:#fff}.button.is-dark:active,.pagination a.is-dark:active{border-color:transparent}.button.is-dark.is-outlined,.pagination a.is-dark.is-outlined{background:transparent;border-color:#222324;color:#222324}.button.is-dark.is-outlined:hover,.pagination a.is-dark.is-outlined:hover,.button.is-dark.is-outlined:focus,.pagination a.is-dark.is-outlined:focus{border-color:#090a0a;color:#090a0a}.button.is-dark.is-inverted,.pagination a.is-dark.is-inverted{background:#fff;color:#222324}.button.is-dark.is-inverted:hover,.pagination a.is-dark.is-inverted:hover{background:#f2f2f2}.button.is-dark.is-inverted.is-outlined,.pagination a.is-dark.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-dark.is-inverted.is-outlined:hover,.pagination a.is-dark.is-inverted.is-outlined:hover{background:rgba(0,0,0,0.05)}.button.is-dark.is-loading:after,.pagination a.is-dark.is-loading:after{border-color:transparent transparent #fff #fff !important}.button.is-primary,.pagination a.is-primary{background:#1fc8db;border-color:transparent;color:#fff}.button.is-primary:hover,.pagination a.is-primary:hover,.button.is-primary:focus,.pagination a.is-primary:focus{background:#199fae;border-color:transparent;color:#fff}.button.is-primary:active,.pagination a.is-primary:active{border-color:transparent}.button.is-primary.is-outlined,.pagination a.is-primary.is-outlined{background:transparent;border-color:#1fc8db;color:#1fc8db}.button.is-primary.is-outlined:hover,.pagination a.is-primary.is-outlined:hover,.button.is-primary.is-outlined:focus,.pagination a.is-primary.is-outlined:focus{border-color:#199fae;color:#199fae}.button.is-primary.is-inverted,.pagination a.is-primary.is-inverted{background:#fff;color:#1fc8db}.button.is-primary.is-inverted:hover,.pagination a.is-primary.is-inverted:hover{background:#f2f2f2}.button.is-primary.is-inverted.is-outlined,.pagination a.is-primary.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined:hover,.pagination a.is-primary.is-inverted.is-outlined:hover{background:rgba(0,0,0,0.05)}.button.is-primary.is-loading:after,.pagination a.is-primary.is-loading:after{border-color:transparent transparent #fff #fff !important}.button.is-info,.pagination a.is-info{background:#42afe3;border-color:transparent;color:#fff}.button.is-info:hover,.pagination a.is-info:hover,.button.is-info:focus,.pagination a.is-info:focus{background:#1f99d3;border-color:transparent;color:#fff}.button.is-info:active,.pagination a.is-info:active{border-color:transparent}.button.is-info.is-outlined,.pagination a.is-info.is-outlined{background:transparent;border-color:#42afe3;color:#42afe3}.button.is-info.is-outlined:hover,.pagination a.is-info.is-outlined:hover,.button.is-info.is-outlined:focus,.pagination a.is-info.is-outlined:focus{border-color:#1f99d3;color:#1f99d3}.button.is-info.is-inverted,.pagination a.is-info.is-inverted{background:#fff;color:#42afe3}.button.is-info.is-inverted:hover,.pagination a.is-info.is-inverted:hover{background:#f2f2f2}.button.is-info.is-inverted.is-outlined,.pagination a.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined:hover,.pagination a.is-info.is-inverted.is-outlined:hover{background:rgba(0,0,0,0.05)}.button.is-info.is-loading:after,.pagination a.is-info.is-loading:after{border-color:transparent transparent #fff #fff !important}.button.is-success,.pagination a.is-success{background:#97cd76;border-color:transparent;color:#fff}.button.is-success:hover,.pagination a.is-success:hover,.button.is-success:focus,.pagination a.is-success:focus{background:#7bbf51;border-color:transparent;color:#fff}.button.is-success:active,.pagination a.is-success:active{border-color:transparent}.button.is-success.is-outlined,.pagination a.is-success.is-outlined{background:transparent;border-color:#97cd76;color:#97cd76}.button.is-success.is-outlined:hover,.pagination a.is-success.is-outlined:hover,.button.is-success.is-outlined:focus,.pagination a.is-success.is-outlined:focus{border-color:#7bbf51;color:#7bbf51}.button.is-success.is-inverted,.pagination a.is-success.is-inverted{background:#fff;color:#97cd76}.button.is-success.is-inverted:hover,.pagination a.is-success.is-inverted:hover{background:#f2f2f2}.button.is-success.is-inverted.is-outlined,.pagination a.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined:hover,.pagination a.is-success.is-inverted.is-outlined:hover{background:rgba(0,0,0,0.05)}.button.is-success.is-loading:after,.pagination a.is-success.is-loading:after{border-color:transparent transparent #fff #fff !important}.button.is-warning,.pagination a.is-warning{background:#fce473;border-color:transparent;color:rgba(0,0,0,0.5)}.button.is-warning:hover,.pagination a.is-warning:hover,.button.is-warning:focus,.pagination a.is-warning:focus{background:#fbda41;border-color:transparent;color:rgba(0,0,0,0.5)}.button.is-warning:active,.pagination a.is-warning:active{border-color:transparent}.button.is-warning.is-outlined,.pagination a.is-warning.is-outlined{background:transparent;border-color:#fce473;color:#fce473}.button.is-warning.is-outlined:hover,.pagination a.is-warning.is-outlined:hover,.button.is-warning.is-outlined:focus,.pagination a.is-warning.is-outlined:focus{border-color:#fbda41;color:#fbda41}.button.is-warning.is-inverted,.pagination a.is-warning.is-inverted{background:rgba(0,0,0,0.5);color:#fce473}.button.is-warning.is-inverted:hover,.pagination a.is-warning.is-inverted:hover{background:rgba(0,0,0,0.5)}.button.is-warning.is-inverted.is-outlined,.pagination a.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.5);color:rgba(0,0,0,0.5)}.button.is-warning.is-inverted.is-outlined:hover,.pagination a.is-warning.is-inverted.is-outlined:hover{background:rgba(0,0,0,0.05)}.button.is-warning.is-loading:after,.pagination a.is-warning.is-loading:after{border-color:transparent transparent rgba(0,0,0,0.5) rgba(0,0,0,0.5) !important}.button.is-danger,.pagination a.is-danger{background:#ed6c63;border-color:transparent;color:#fff}.button.is-danger:hover,.pagination a.is-danger:hover,.button.is-danger:focus,.pagination a.is-danger:focus{background:#e84135;border-color:transparent;color:#fff}.button.is-danger:active,.pagination a.is-danger:active{border-color:transparent}.button.is-danger.is-outlined,.pagination a.is-danger.is-outlined{background:transparent;border-color:#ed6c63;color:#ed6c63}.button.is-danger.is-outlined:hover,.pagination a.is-danger.is-outlined:hover,.button.is-danger.is-outlined:focus,.pagination a.is-danger.is-outlined:focus{border-color:#e84135;color:#e84135}.button.is-danger.is-inverted,.pagination a.is-danger.is-inverted{background:#fff;color:#ed6c63}.button.is-danger.is-inverted:hover,.pagination a.is-danger.is-inverted:hover{background:#f2f2f2}.button.is-danger.is-inverted.is-outlined,.pagination a.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined:hover,.pagination a.is-danger.is-inverted.is-outlined:hover{background:rgba(0,0,0,0.05)}.button.is-danger.is-loading:after,.pagination a.is-danger.is-loading:after{border-color:transparent transparent #fff #fff !important}.button.is-link,.pagination a.is-link{border-color:transparent;color:#69707a;text-decoration:underline}.button.is-link:hover,.pagination a.is-link:hover,.button.is-link:focus,.pagination a.is-link:focus{background:#d3d6db;color:#222324}.button.is-small,.pagination a.is-small{border-radius:2px;font-size:11px;height:24px;line-height:16px;padding:3px 6px}.button.is-medium,.pagination a.is-medium{font-size:18px;height:40px;padding:7px 14px}.button.is-large,.pagination a.is-large{font-size:22px;height:48px;padding:11px 20px}.button.is-fullwidth,.pagination a.is-fullwidth{display:block;width:100%}.button.is-flexible,.pagination a.is-flexible{height:auto}.button.is-loading,.pagination a.is-loading{color:transparent;pointer-events:none}.button.is-loading:after,.pagination a.is-loading:after{left:50%;margin-left:-8px;margin-top:-8px;position:absolute;top:50%;position:absolute !important}.button.is-disabled,.pagination a.is-disabled,.button[disabled],.pagination a[disabled]{opacity:0.5;pointer-events:none}.title,.subtitle{font-weight:300}.title em,.title span,.subtitle em,.subtitle span{font-weight:300}.title strong,.subtitle strong{font-weight:500}.title a:hover,.subtitle a:hover{border-bottom:1px solid}.title .tag,.subtitle .tag{vertical-align:bottom}.title{color:#222324;font-size:28px;line-height:1}.title strong{color:inherit}.title code{display:inline-block;font-size:28px}.title+.subtitle{margin-top:-10px}.title+.highlight{margin-top:-10px}.title.is-normal{font-weight:400}.title.is-normal strong{font-weight:700}.title.is-1{font-size:48px}.title.is-1 code{font-size:40px}.title.is-2{font-size:40px}.title.is-2 code{font-size:28px}.title.is-3{font-size:28px}.title.is-3 code{font-size:24px}.title.is-4{font-size:24px}.title.is-4 code{font-size:18px}.title.is-5{font-size:18px}.title.is-5 code{font-size:14px}.title.is-6{font-size:14px}.title.is-6 code{font-size:14px}@media screen and (min-width: 769px){.title+.subtitle{margin-top:-15px}}.subtitle{font-size:18px;line-height:1.125}.subtitle+.title{margin-top:-20px}.subtitle strong{color:#222324}.subtitle code{border-radius:3px;display:inline-block;font-size:14px;padding:2px 3px;vertical-align:top}.subtitle+.text{margin-top:20px}.subtitle.is-normal{font-weight:400}.subtitle.is-normal strong{font-weight:700}.subtitle.is-1{font-size:48px}.subtitle.is-1 code{font-size:40px}.subtitle.is-2{font-size:40px}.subtitle.is-2 code{font-size:28px}.subtitle.is-3{font-size:28px}.subtitle.is-3 code{font-size:24px}.subtitle.is-4{font-size:24px}.subtitle.is-4 code{font-size:18px}.subtitle.is-5{font-size:18px}.subtitle.is-5 code{font-size:14px}.subtitle.is-6{font-size:14px}.subtitle.is-6 code{font-size:14px}.image{display:block;position:relative}.image img{display:block}.image.is-square img,.image.is-1by1 img,.image.is-4by3 img,.image.is-3by2 img,.image.is-16by9 img,.image.is-2by1 img{bottom:0;left:0;position:absolute;right:0;top:0;height:100%;width:100%}.image.is-square,.image.is-1by1{padding-top:100%}.image.is-4by3{padding-top:75%}.image.is-3by2{padding-top:66.6666%}.image.is-16by9{padding-top:56.25%}.image.is-2by1{padding-top:50%}.image.is-16x16{height:16px;width:16px}.image.is-24x24{height:24px;width:24px}.image.is-32x32{height:32px;width:32px}.image.is-48x48{height:48px;width:48px}.image.is-64x64{height:64px;width:64px}.image.is-96x96{height:96px;width:96px}.image.is-128x128{height:128px;width:128px}.message-body{border:1px solid #d3d6db;border-radius:3px;padding:12px 15px}.message-body strong{color:inherit}.message-header{background:#69707a;border-radius:3px 3px 0 0;color:#fff;font-size:10px;font-weight:bold;letter-spacing:1px;padding:3px 8px;text-transform:uppercase}.message-header+.message-body{border-radius:0 0 3px 3px;border-top:none}.message{background:#f5f7fa;border-radius:3px}.message.is-dark{background:#f5f5f5}.message.is-dark .message-header{background:#222324;color:#fff}.message.is-dark .message-body{border-color:#222324;color:gray}.message.is-primary{background:#edfbfc}.message.is-primary .message-header{background:#1fc8db;color:#fff}.message.is-primary .message-body{border-color:#1fc8db;color:gray}.message.is-info{background:#edf7fc}.message.is-info .message-header{background:#42afe3;color:#fff}.message.is-info .message-body{border-color:#42afe3;color:gray}.message.is-success{background:#f4faf0}.message.is-success .message-header{background:#97cd76;color:#fff}.message.is-success .message-body{border-color:#97cd76;color:gray}.message.is-warning{background:#fffbeb}.message.is-warning .message-header{background:#fce473;color:rgba(0,0,0,0.5)}.message.is-warning .message-body{border-color:#fce473;color:#666}.message.is-danger{background:#fdeeed}.message.is-danger .message-header{background:#ed6c63;color:#fff}.message.is-danger .message-body{border-color:#ed6c63;color:gray}.notification{background:#f5f7fa;border-radius:3px;padding:16px 20px;position:relative}.notification:after{clear:both;content:" ";display:table}.notification .title{color:inherit}.notification.is-dark{background:#222324;color:#fff}.notification.is-primary{background:#1fc8db;color:#fff}.notification.is-info{background:#42afe3;color:#fff}.notification.is-success{background:#97cd76;color:#fff}.notification.is-warning{background:#fce473;color:rgba(0,0,0,0.5)}.notification.is-danger{background:#ed6c63;color:#fff}.notification .delete,.notification .modal-close{background:rgba(0,0,0,0.2);border-radius:0 3px;float:right;margin:-16px -20px 0 20px}.notification .delete:hover,.notification .modal-close:hover{background:rgba(0,0,0,0.5)}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:290486px;display:block;height:12px;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background:#d3d6db}.progress::-webkit-progress-value{background:#69707a}.progress::-moz-progress-bar{background:#69707a}.progress.is-small{height:8px}.progress.is-medium{height:16px}.progress.is-large{height:20px}.progress.is-dark::-webkit-progress-value{background:#222324}.progress.is-dark::-moz-progress-bar{background:#222324}.progress.is-primary::-webkit-progress-value{background:#1fc8db}.progress.is-primary::-moz-progress-bar{background:#1fc8db}.progress.is-info::-webkit-progress-value{background:#42afe3}.progress.is-info::-moz-progress-bar{background:#42afe3}.progress.is-success::-webkit-progress-value{background:#97cd76}.progress.is-success::-moz-progress-bar{background:#97cd76}.progress.is-warning::-webkit-progress-value{background:#fce473}.progress.is-warning::-moz-progress-bar{background:#fce473}.progress.is-danger::-webkit-progress-value{background:#ed6c63}.progress.is-danger::-moz-progress-bar{background:#ed6c63}.delete,.modal-close{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background:rgba(0,0,0,0.2);border:none;border-radius:290486px;cursor:pointer;display:inline-block;height:24px;position:relative;vertical-align:top;width:24px}.delete:before,.modal-close:before,.delete:after,.modal-close:after{background:white;content:"";display:block;height:2px;left:50%;margin-left:-25%;margin-top:-1px;position:absolute;top:50%;width:50%}.delete:before,.modal-close:before{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.delete:after,.modal-close:after{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.delete:hover,.modal-close:hover{background:#ed6c63}.delete.is-small,.tag:not(.is-large) .delete,.tag:not(.is-large) .modal-close,.is-small.modal-close{height:16px;width:16px}.delete.is-medium,.is-medium.modal-close{height:32px;width:32px}.delete.is-large,.is-large.modal-close{height:40px;width:40px}.icon{display:inline-block;font-size:21px;height:24px;line-height:24px;text-align:center;vertical-align:top;width:24px}.icon .fa{font-size:inherit;line-height:inherit}.icon.is-small{display:inline-block;font-size:14px;height:16px;line-height:16px;text-align:center;vertical-align:top;width:16px}.icon.is-medium{display:inline-block;font-size:28px;height:32px;line-height:32px;text-align:center;vertical-align:top;width:32px}.icon.is-large{display:inline-block;font-size:42px;height:48px;line-height:48px;text-align:center;vertical-align:top;width:48px}.hamburger,.header-toggle{cursor:pointer;display:block;height:50px;position:relative;width:50px}.hamburger span,.header-toggle span{background:#69707a;display:block;height:1px;left:50%;margin-left:-7px;position:absolute;top:50%;-webkit-transition:none 86ms ease-out;transition:none 86ms ease-out;-webkit-transition-property:background, left, opacity, -webkit-transform;transition-property:background, left, opacity, -webkit-transform;transition-property:background, left, opacity, transform;transition-property:background, left, opacity, transform, -webkit-transform;width:15px}.hamburger span:nth-child(1),.header-toggle span:nth-child(1){margin-top:-6px}.hamburger span:nth-child(2),.header-toggle span:nth-child(2){margin-top:-1px}.hamburger span:nth-child(3),.header-toggle span:nth-child(3){margin-top:4px}.hamburger:hover,.header-toggle:hover{background:#f5f7fa}.hamburger.is-active span,.is-active.header-toggle span{background:#1fc8db}.hamburger.is-active span:nth-child(1),.is-active.header-toggle span:nth-child(1){margin-left:-5px;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-transform-origin:left top;transform-origin:left top}.hamburger.is-active span:nth-child(2),.is-active.header-toggle span:nth-child(2){opacity:0}.hamburger.is-active span:nth-child(3),.is-active.header-toggle span:nth-child(3){margin-left:-5px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:left bottom;transform-origin:left bottom}@media screen and (min-width: 769px){.hamburger,.header-toggle{height:50px;width:50px}}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.highlight{font-size:12px;font-weight:normal;max-width:100%;overflow:hidden;padding:0}.highlight pre{overflow:auto;max-width:100%}.image{display:block;position:relative;vertical-align:top}.image img{bottom:0;left:0;position:absolute;right:0;top:0;display:block;width:100%}.image.is-3x2{padding-top:66.6666%}.loader,.control.is-loading:after,.button.is-loading:after,.pagination a.is-loading:after{-webkit-animation:spin-around 500ms infinite linear;animation:spin-around 500ms infinite linear;border:2px solid #d3d6db;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:16px;position:relative;width:16px}.number{background:#f5f7fa;border-radius:290486px;display:inline-block;font-size:18px;vertical-align:top}.tag{background:#f5f7fa;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.1);color:#69707a;display:inline-block;font-size:12px;height:24px;line-height:16px;padding:4px 10px;vertical-align:top;white-space:nowrap}.tag.is-dark{background:#69707a;color:#fff}.tag.is-rounded{border-radius:290486px}.tag.is-medium{box-shadow:inset 0 -2px 0 rgba(0,0,0,0.1);font-size:14px;height:32px;padding:7px 14px 9px}.tag:not(.is-large) .delete,.tag:not(.is-large) .modal-close{margin-left:4px;margin-right:-6px}.tag.is-large{box-shadow:inset 0 -2px 0 rgba(0,0,0,0.1);font-size:18px;height:40px;line-height:24px;padding:7px 18px 9px}.tag.is-large .delete,.tag.is-large .modal-close{margin-left:4px;margin-right:-8px}.tag.is-dark{background:#222324;color:#fff}.tag.is-primary{background:#1fc8db;color:#fff}.tag.is-info{background:#42afe3;color:#fff}.tag.is-success{background:#97cd76;color:#fff}.tag.is-warning{background:#fce473;color:rgba(0,0,0,0.5)}.tag.is-danger{background:#ed6c63;color:#fff}.column{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding:10px}.columns.is-mobile>.column.is-half{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:50%}.columns.is-mobile>.column.is-third{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:33.3333%}.columns.is-mobile>.column.is-quarter{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:25%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-quarter{margin-left:25%}.columns.is-mobile>.column.is-1{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:8.33333%}.columns.is-mobile>.column.is-offset-1{margin-left:8.33333%}.columns.is-mobile>.column.is-2{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:16.66667%}.columns.is-mobile>.column.is-offset-2{margin-left:16.66667%}.columns.is-mobile>.column.is-3{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:33.33333%}.columns.is-mobile>.column.is-offset-4{margin-left:33.33333%}.columns.is-mobile>.column.is-5{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:41.66667%}.columns.is-mobile>.column.is-offset-5{margin-left:41.66667%}.columns.is-mobile>.column.is-6{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:58.33333%}.columns.is-mobile>.column.is-offset-7{margin-left:58.33333%}.columns.is-mobile>.column.is-8{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:66.66667%}.columns.is-mobile>.column.is-offset-8{margin-left:66.66667%}.columns.is-mobile>.column.is-9{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:83.33333%}.columns.is-mobile>.column.is-offset-10{margin-left:83.33333%}.columns.is-mobile>.column.is-11{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:91.66667%}.columns.is-mobile>.column.is-offset-11{margin-left:91.66667%}@media screen and (max-width: 768px){.column.is-half-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:50%}.column.is-third-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:33.3333%}.column.is-quarter-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:25%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-third-mobile{margin-left:33.3333%}.column.is-offset-quarter-mobile{margin-left:25%}.column.is-1-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1-mobile{margin-left:8.33333%}.column.is-2-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2-mobile{margin-left:16.66667%}.column.is-3-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4-mobile{margin-left:33.33333%}.column.is-5-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5-mobile{margin-left:41.66667%}.column.is-6-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7-mobile{margin-left:58.33333%}.column.is-8-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8-mobile{margin-left:66.66667%}.column.is-9-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10-mobile{margin-left:83.33333%}.column.is-11-mobile{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11-mobile{margin-left:91.66667%}}@media screen and (min-width: 769px){.column.is-half,.column.is-half-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:50%}.column.is-third,.column.is-third-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:33.3333%}.column.is-quarter,.column.is-quarter-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:25%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-third,.column.is-offset-third-tablet{margin-left:33.3333%}.column.is-offset-quarter,.column.is-offset-quarter-tablet{margin-left:25%}.column.is-1,.column.is-1-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.33333%}.column.is-2,.column.is-2-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.66667%}.column.is-3,.column.is-3-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.33333%}.column.is-5,.column.is-5-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.66667%}.column.is-6,.column.is-6-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.33333%}.column.is-8,.column.is-8-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.66667%}.column.is-9,.column.is-9-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.33333%}.column.is-11,.column.is-11-tablet{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.66667%}}@media screen and (min-width: 980px){.column.is-half-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:50%}.column.is-third-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:33.3333%}.column.is-quarter-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:25%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-third-desktop{margin-left:33.3333%}.column.is-offset-quarter-desktop{margin-left:25%}.column.is-1-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:8.33333%}.column.is-offset-1-desktop{margin-left:8.33333%}.column.is-2-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:16.66667%}.column.is-offset-2-desktop{margin-left:16.66667%}.column.is-3-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:33.33333%}.column.is-offset-4-desktop{margin-left:33.33333%}.column.is-5-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:41.66667%}.column.is-offset-5-desktop{margin-left:41.66667%}.column.is-6-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:58.33333%}.column.is-offset-7-desktop{margin-left:58.33333%}.column.is-8-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:66.66667%}.column.is-offset-8-desktop{margin-left:66.66667%}.column.is-9-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:83.33333%}.column.is-offset-10-desktop{margin-left:83.33333%}.column.is-11-desktop{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none;width:91.66667%}.column.is-offset-11-desktop{margin-left:91.66667%}}.columns{margin-left:-10px;margin-right:-10px;margin-top:-10px}.columns:last-child{margin-bottom:-10px}.columns:not(:last-child){margin-bottom:10px}.columns.is-centered{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.columns.is-mobile{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.columns.is-gapless{margin-left:0;margin-right:0}.columns.is-gapless:not(:last-child){margin-bottom:20px}.columns.is-gapless>.column{margin:0;padding:0}.columns.is-multiline{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.columns.is-vcentered{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;-ms-grid-row-align:center;align-items:center}@media screen and (min-width: 769px){.columns.is-grid{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.columns.is-grid>.column{-webkit-flex-basis:33.3333%;-ms-flex-preferred-size:33.3333%;flex-basis:33.3333%;max-width:33.3333%;padding:10px;width:33.3333%}.columns.is-grid>.column+.column{margin-left:0}}@media screen and (min-width: 769px){.columns:not(.is-desktop){display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}}@media screen and (min-width: 980px){.columns.is-desktop{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}}.navbar-item .title,.navbar-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){.navbar-item:not(:last-child){margin-bottom:10px}}.navbar code{border-radius:3px}.navbar img{display:inline-block;vertical-align:top}@media screen and (min-width: 769px){.navbar{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.navbar>.navbar-item:not(.is-narrow){-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}}.navbar-left .navbar-item.is-flexible,.navbar-right .navbar-item.is-flexible{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.navbar-left .navbar-item:not(:last-child),.navbar-right .navbar-item:not(:last-child){margin-right:10px}@media screen and (max-width: 768px){.navbar-left+.navbar-right{margin-top:20px}}@media screen and (min-width: 769px){.navbar-left{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}}@media screen and (min-width: 769px){.navbar-right{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}}.card-header{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;box-shadow:0 1px 2px rgba(0,0,0,0.1);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-height:40px}.card-header-title{-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;color:#222324;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bold;padding:10px}.card-header-icon{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;cursor:pointer;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;width:40px}.card-image{display:block;position:relative}.card-content{padding:20px}.card-content .title+.subtitle{margin-top:-20px}.card-footer{background:#f5f7fa;border-top:1px solid #d3d6db;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.card-footer-item{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding:10px}.card-footer-item:not(:last-child){border-right:1px solid #d3d6db}.card{background:white;box-shadow:0 2px 3px rgba(0,0,0,0.1),0 0 0 1px rgba(0,0,0,0.1);max-width:100%;position:relative;width:300px}.card .media:not(:last-child){margin-bottom:10px}.card.is-rounded{border-radius:5px}.card.is-fullwidth{width:100%}.table{background:white;color:#222324;margin-bottom:20px;width:100%}.table th,.table td{border:1px solid #d3d6db;border-width:0 0 1px;padding:8px 10px;vertical-align:top}.table th.table-narrow,.table td.table-narrow{white-space:nowrap;width:1%}.table th.table-link,.table td.table-link{padding:0}.table th.table-link>a,.table td.table-link>a{display:block;padding:8px 10px}.table th.table-link>a:hover,.table td.table-link>a:hover{background:#1fc8db;color:#fff}.table th.table-icon,.table td.table-icon{padding:5px;text-align:center;white-space:nowrap;width:1%}.table th.table-icon .fa,.table td.table-icon .fa{display:inline-block;font-size:21px;height:24px;line-height:24px;text-align:center;vertical-align:top;width:24px}.table th.table-icon.table-link,.table td.table-icon.table-link{padding:0}.table th.table-icon.table-link>a,.table td.table-icon.table-link>a{padding:5px}.table th{color:#222324;text-align:left}.table tr:hover{background:rgba(245,247,250,0.5);color:#222324}.table tr:last-child td{border-bottom-width:0}.table thead th,.table thead td{border-width:0 0 2px;color:#aeb1b5}.table tfoot th,.table tfoot td{border-width:2px 0 0;color:#aeb1b5}.table.is-bordered th,.table.is-bordered td{border-width:1px}.table.is-bordered tr:last-child td{border-bottom-width:1px}.table.is-narrow th,.table.is-narrow td{padding:5px 10px}.table.is-narrow th.table-link,.table.is-narrow td.table-link{padding:0}.table.is-narrow th.table-link>a,.table.is-narrow td.table-link>a{padding:5px 10px}.table.is-narrow th.table-icon,.table.is-narrow td.table-icon{padding:2px}.table.is-narrow th.table-icon.table-link,.table.is-narrow td.table-icon.table-link{padding:0}.table.is-narrow th.table-icon.table-link>a,.table.is-narrow td.table-icon.table-link>a{padding:2px}.table.is-striped tbody tr:nth-child(2n){background:rgba(245,247,250,0.5)}.table.is-striped tbody tr:nth-child(2n):hover{background:#f5f7fa}.tabs{line-height:24px;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs .fa{font-size:14px;line-height:20px;margin:2px -2px;width:20px}.tabs a{border-bottom:1px solid #d3d6db;color:#69707a;display:block;margin-bottom:-1px;padding:5px 0;vertical-align:top}.tabs a:hover{border-bottom-color:#222324;color:#222324}.tabs li{display:block;vertical-align:top}.tabs li+li{margin-left:20px}.tabs li.is-active a{border-bottom-color:#1fc8db;color:#1fc8db}.tabs ul{border-bottom:1px solid #d3d6db;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tabs.is-centered a{padding:5px 10px}.tabs.is-centered li+li{margin-left:0}.tabs.is-centered ul{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.tabs.is-right ul{-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:3px 3px 0 0;padding:5px 15px}.tabs.is-boxed a:hover{background:#f5f7fa;border-bottom-color:#d3d6db}.tabs.is-boxed li+li{margin-left:5px}.tabs.is-boxed li.is-active a{background:white;border-color:#d3d6db;border-bottom-color:transparent}.tabs.is-boxed.is-centered li,.tabs.is-boxed.is-centered li+li{margin:0 2px}.tabs.is-toggle a{border:1px solid #d3d6db;margin-bottom:0;padding:5px 10px;position:relative}.tabs.is-toggle a:hover{background:#f5f7fa;border-color:#aeb1b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-radius:3px 0 0 3px}.tabs.is-toggle li:last-child a{border-radius:0 3px 3px 0}.tabs.is-toggle li.is-active a{background:#1fc8db;border-color:#1fc8db;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}@media screen and (min-width: 769px){.tabs.is-fullwidth li{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.tabs.is-fullwidth li+li{margin-left:0}.tabs.is-fullwidth ul{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}}.media-number{background:#f5f7fa;border-radius:290486px;display:inline-block;font-size:18px;height:32px;line-height:24px;min-width:32px;padding:4px 8px;text-align:center;vertical-align:top}@media screen and (max-width: 768px){.media-number{margin-bottom:10px}}@media screen and (min-width: 769px){.media-number{margin-right:10px}}.media-left{margin-right:10px}.media-right{margin-left:10px}.media-content{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;text-align:left}.media{-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;text-align:left}.media .content:not(:last-child){margin-bottom:10px}.media .media{border-top:1px solid rgba(211,214,219,0.5);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-top:10px}.media .media .textarea{border-radius:2px;font-size:11px;height:24px;line-height:16px;padding:3px 6px}.media .media .button,.media .media .pagination a,.pagination .media .media a{border-radius:2px;font-size:11px;height:24px;line-height:16px;padding:3px 6px}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:5px}.media .media .media{font-size:12px;padding-top:5px}.media .media .media+.media{margin-top:5px}.media+.media{border-top:1px solid rgba(211,214,219,0.5);margin-top:10px;padding-top:10px}.media.is-large+.media{margin-top:20px;padding-top:20px}@media screen and (min-width: 769px){.media.is-large .media-number{margin-right:20px}}.menu-nav a{display:block;padding:5px 10px}.menu-list a{border-radius:2px;color:#69707a;display:block;padding:5px 10px}.menu-list a:hover{background:#f5f7fa;color:#1fc8db}.menu-list a.is-active{background:#1fc8db;color:#fff}.menu-list li ul{border-left:1px solid #d3d6db;margin:10px;padding-left:10px}.menu-label{color:#aeb1b5;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.menu-label:not(:first-child){margin-top:20px}.pagination{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;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;text-align:center}.pagination a{display:block;min-width:32px;padding:3px 8px}.pagination a.is-active{background:#1fc8db;border-color:#1fc8db;color:#fff}.pagination span{color:#aeb1b5;display:block;margin:0 4px}.pagination li{margin:0 2px}.pagination ul{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}@media screen and (max-width: 768px){.pagination{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.pagination>a{width:calc(50% - 5px)}.pagination>a:not(:first-child){margin-left:10px}.pagination li{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.pagination ul{margin-top:10px}}@media screen and (min-width: 769px){.pagination>a:not(:first-child){-webkit-box-ordinal-group:2;-webkit-order:1;-ms-flex-order:1;order:1}}.panel-icon{display:inline-block;font-size:14px;height:16px;line-height:16px;text-align:center;vertical-align:top;width:16px;color:#aeb1b5;float:left;margin:0 4px 0 -2px}.panel-icon .fa{font-size:inherit;line-height:inherit}.panel-heading{background:#f5f7fa;border-bottom:1px solid #d3d6db;border-radius:4px 4px 0 0;color:#222324;font-size:18px;font-weight:300;padding:10px}.panel-list a{color:#69707a}.panel-list a:hover{color:#1fc8db}.panel-tabs{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;font-size:11px;padding:5px 10px 0;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.panel-tabs:not(:last-child){border-bottom:1px solid #d3d6db}.panel-tabs a{border-bottom:1px solid #d3d6db;margin-bottom:-1px;padding:5px}.panel-tabs a.is-active{border-bottom-color:#222324;color:#222324}.panel-block{color:#222324;display:block;line-height:16px;padding:10px}.panel-block:not(:last-child){border-bottom:1px solid #d3d6db}.panel-block .checkbox,.panel-block .panel-checkbox{border:1px solid transparent;border-radius:3px;display:block;padding:8px;padding-left:32px}.panel-block .checkbox input,.panel-block .panel-checkbox input{left:9px;top:9px}.panel-block .checkbox:hover,.panel-block .panel-checkbox:hover{border-color:#1fc8db}a.panel-block:hover{background:#f5f7fa}.panel-checkbox{display:block;padding:9px 10px 9px 30px}.panel-checkbox:not(:last-child){border-bottom:1px solid #d3d6db}.panel-checkbox input{left:8px;top:10px}.panel{border:1px solid #d3d6db;border-radius:5px}.panel:not(:last-child){margin-bottom:20px}.modal-background{bottom:0;left:0;position:absolute;right:0;top:0;background:rgba(0,0,0,0.86)}.modal-content{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){.modal-content{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal{bottom:0;left:0;position:absolute;right:0;top:0;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;-ms-grid-row-align:center;align-items:center;display:none;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;overflow:hidden;position:fixed;z-index:1986}.modal.is-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.box{background:white;border-radius:5px;box-shadow:0 2px 3px rgba(0,0,0,0.1),0 0 0 1px rgba(0,0,0,0.1);padding:20px}.header{background:white;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;line-height:24px;position:relative;text-align:center;z-index:2}.header:after{clear:both;content:" ";display:table}.header .container{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%}.header.has-shadow{box-shadow:0 1px 2px rgba(0,0,0,0.1)}@media screen and (max-width: 768px){.header .container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}}@media screen and (min-width: 769px){.header{height:50px}}.header-toggle{position:absolute;right:0;top:0}@media screen and (min-width: 769px){.header-toggle{display:none}}.header-item{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:10px}.header-item img{max-height:24px}.header-item a{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1}.header-item .fa{font-size:21px;line-height:24px}.header-item .button+.button,.header-item .pagination a+.button,.pagination .header-item a+.button,.header-item .pagination .button+a,.pagination .header-item .button+a,.header-item .pagination a+a,.pagination .header-item a+a{margin-left:10px}@media screen and (max-width: 768px){.header-item{text-align:left}}.header-item a,a.header-item{color:#69707a}.header-item a:hover,a.header-item:hover{color:#222324}.header-item a.is-active,a.header-item.is-active{color:#222324}.header-icon{display:inline-block;font-size:14px;height:24px;line-height:24px;text-align:center;vertical-align:top;width:24px;color:#69707a;margin:0 5px}.header-icon:hover{color:#222324}.header-tab{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;-ms-grid-row-align:center;align-items:center;border-bottom:1px solid transparent;color:#69707a;display:block;height:50px;line-height:24px;padding:13px 15px}.header-tab:hover{border-bottom:1px solid #1fc8db}.header-tab.is-active{border-bottom:3px solid #1fc8db;color:#1fc8db}.header-left{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;overflow:hidden;overflow-x:auto;white-space:nowrap}@media screen and (max-width: 768px){.header-left{height:50px}}@media screen and (min-width: 980px){.header-left .header-item:first-child{padding-left:0}}.header-right{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;-ms-grid-row-align:stretch;align-items:stretch}@media screen and (min-width: 769px){.header-right{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}}@media screen and (min-width: 980px){.header-right .header-item:last-child{padding-right:0}}.header-full{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;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;text-align:center;width:100%}.header-full>.header-item{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;padding:0}.header-full>.header-item>a{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;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;width:100%}@media screen and (max-width: 768px){.header-menu{box-shadow:0 4px 7px rgba(0,0,0,0.1);display:none}.header-menu .header-item{border-top:1px solid rgba(211,214,219,0.5);padding:10px}.header-menu.is-active{display:block}}.header.is-centered{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.header.is-centered .header-left,.header.is-centered .header-right{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.header.is-small{background:#f5f7fa;box-shadow:none;height:40px;z-index:1}.header.is-small .container{height:40px}.header.is-small .header-tab{font-size:13px;height:40px;padding:8px 10px}.header.is-small .header-tab:hover,.header.is-small .header-tab.is-active{border-bottom-width:2px}.hero-video{bottom:0;left:0;position:absolute;right:0;top:0;overflow:hidden}.hero-video.is-transparent{opacity:0.3}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;-webkit-transform:translate3d(-50%, -50%, 0);transform:translate3d(-50%, -50%, 0)}@media screen and (max-width: 768px){.hero-video{display:none}}.hero-content{padding:40px 20px}@media screen and (min-width: 980px){.hero-content{padding:40px 0}}.hero-buttons{margin-top:20px}@media screen and (max-width: 768px){.hero-buttons .button,.hero-buttons .pagination a,.pagination .hero-buttons a{display:block}.hero-buttons .button:not(:last-child),.hero-buttons .pagination a:not(:last-child),.pagination .hero-buttons a:not(:last-child){margin-bottom:10px}}@media screen and (min-width: 769px){.hero-buttons{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}.hero-buttons .button:not(:last-child),.hero-buttons .pagination a:not(:last-child),.pagination .hero-buttons a:not(:last-child){margin-right:20px}}.hero{background:white;text-align:center}.hero .header{background:none}.hero .header .container{box-shadow:0 1px 0 rgba(211,214,219,0.3)}.hero .tabs a{border:none}.hero .tabs ul{border-bottom:none}.hero .tabs.is-boxed a{padding:8px 15px}.hero.is-dark{background:#222324;color:#fff}.hero.is-dark .title{color:#fff}.hero.is-dark .title a,.hero.is-dark .title strong{color:inherit}.hero.is-dark .subtitle{color:rgba(255,255,255,0.7)}.hero.is-dark .subtitle strong{color:#fff}.hero.is-dark .header .container{box-shadow:0 1px 0 rgba(255,255,255,0.2)}.hero.is-dark .header-icon,.hero.is-dark a.header-item,.hero.is-dark .header-item>a:not(.button){color:rgba(255,255,255,0.5)}.hero.is-dark .header-icon:hover,.hero.is-dark .header-icon.is-active,.hero.is-dark a.header-item:hover,.hero.is-dark a.header-item.is-active,.hero.is-dark .header-item>a:not(.button):hover,.hero.is-dark .header-item>a:not(.button).is-active{color:#fff}.hero.is-dark .tabs a{color:#fff;opacity:0.5}.hero.is-dark .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a{opacity:1}.hero.is-dark .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a{color:#fff}.hero.is-dark .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover{background:rgba(0,0,0,0.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background:#fff;color:#222324}.hero.is-dark.is-bold{background-image:-webkit-linear-gradient(309deg, #080a0b 0%, #222324 71%, #2c2e34 100%);background-image:linear-gradient(141deg, #080a0b 0%, #222324 71%, #2c2e34 100%)}@media screen and (max-width: 768px){.hero.is-dark .header-toggle span{background:#fff}.hero.is-dark .header-toggle:hover{background:rgba(0,0,0,0.1)}.hero.is-dark .header-toggle.is-active span{background:#fff}.hero.is-dark .header-menu .header-item{border-top-color:rgba(255,255,255,0.2)}}.hero.is-primary{background:#1fc8db;color:#fff}.hero.is-primary .title{color:#fff}.hero.is-primary .title a,.hero.is-primary .title strong{color:inherit}.hero.is-primary .subtitle{color:rgba(255,255,255,0.7)}.hero.is-primary .subtitle strong{color:#fff}.hero.is-primary .header .container{box-shadow:0 1px 0 rgba(255,255,255,0.2)}.hero.is-primary .header-icon,.hero.is-primary a.header-item,.hero.is-primary .header-item>a:not(.button){color:rgba(255,255,255,0.5)}.hero.is-primary .header-icon:hover,.hero.is-primary .header-icon.is-active,.hero.is-primary a.header-item:hover,.hero.is-primary a.header-item.is-active,.hero.is-primary .header-item>a:not(.button):hover,.hero.is-primary .header-item>a:not(.button).is-active{color:#fff}.hero.is-primary .tabs a{color:#fff;opacity:0.5}.hero.is-primary .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a{opacity:1}.hero.is-primary .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover{background:rgba(0,0,0,0.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background:#fff;color:#1fc8db}.hero.is-primary.is-bold{background-image:-webkit-linear-gradient(309deg, #0fb8ad 0%, #1fc8db 71%, #2cb5e8 100%);background-image:linear-gradient(141deg, #0fb8ad 0%, #1fc8db 71%, #2cb5e8 100%)}@media screen and (max-width: 768px){.hero.is-primary .header-toggle span{background:#fff}.hero.is-primary .header-toggle:hover{background:rgba(0,0,0,0.1)}.hero.is-primary .header-toggle.is-active span{background:#fff}.hero.is-primary .header-menu .header-item{border-top-color:rgba(255,255,255,0.2)}}.hero.is-info{background:#42afe3;color:#fff}.hero.is-info .title{color:#fff}.hero.is-info .title a,.hero.is-info .title strong{color:inherit}.hero.is-info .subtitle{color:rgba(255,255,255,0.7)}.hero.is-info .subtitle strong{color:#fff}.hero.is-info .header .container{box-shadow:0 1px 0 rgba(255,255,255,0.2)}.hero.is-info .header-icon,.hero.is-info a.header-item,.hero.is-info .header-item>a:not(.button){color:rgba(255,255,255,0.5)}.hero.is-info .header-icon:hover,.hero.is-info .header-icon.is-active,.hero.is-info a.header-item:hover,.hero.is-info a.header-item.is-active,.hero.is-info .header-item>a:not(.button):hover,.hero.is-info .header-item>a:not(.button).is-active{color:#fff}.hero.is-info .tabs a{color:#fff;opacity:0.5}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background:rgba(0,0,0,0.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background:#fff;color:#42afe3}.hero.is-info.is-bold{background-image:-webkit-linear-gradient(309deg, #13bfdf 0%, #42afe3 71%, #53a1eb 100%);background-image:linear-gradient(141deg, #13bfdf 0%, #42afe3 71%, #53a1eb 100%)}@media screen and (max-width: 768px){.hero.is-info .header-toggle span{background:#fff}.hero.is-info .header-toggle:hover{background:rgba(0,0,0,0.1)}.hero.is-info .header-toggle.is-active span{background:#fff}.hero.is-info .header-menu .header-item{border-top-color:rgba(255,255,255,0.2)}}.hero.is-success{background:#97cd76;color:#fff}.hero.is-success .title{color:#fff}.hero.is-success .title a,.hero.is-success .title strong{color:inherit}.hero.is-success .subtitle{color:rgba(255,255,255,0.7)}.hero.is-success .subtitle strong{color:#fff}.hero.is-success .header .container{box-shadow:0 1px 0 rgba(255,255,255,0.2)}.hero.is-success .header-icon,.hero.is-success a.header-item,.hero.is-success .header-item>a:not(.button){color:rgba(255,255,255,0.5)}.hero.is-success .header-icon:hover,.hero.is-success .header-icon.is-active,.hero.is-success a.header-item:hover,.hero.is-success a.header-item.is-active,.hero.is-success .header-item>a:not(.button):hover,.hero.is-success .header-item>a:not(.button).is-active{color:#fff}.hero.is-success .tabs a{color:#fff;opacity:0.5}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background:rgba(0,0,0,0.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background:#fff;color:#97cd76}.hero.is-success.is-bold{background-image:-webkit-linear-gradient(309deg, #8ecb45 0%, #97cd76 71%, #96d885 100%);background-image:linear-gradient(141deg, #8ecb45 0%, #97cd76 71%, #96d885 100%)}@media screen and (max-width: 768px){.hero.is-success .header-toggle span{background:#fff}.hero.is-success .header-toggle:hover{background:rgba(0,0,0,0.1)}.hero.is-success .header-toggle.is-active span{background:#fff}.hero.is-success .header-menu .header-item{border-top-color:rgba(255,255,255,0.2)}}.hero.is-warning{background:#fce473;color:rgba(0,0,0,0.5)}.hero.is-warning .title{color:rgba(0,0,0,0.5)}.hero.is-warning .title a,.hero.is-warning .title strong{color:inherit}.hero.is-warning .subtitle{color:rgba(0,0,0,0.7)}.hero.is-warning .subtitle strong{color:rgba(0,0,0,0.5)}.hero.is-warning .header .container{box-shadow:0 1px 0 rgba(0,0,0,0.2)}.hero.is-warning .header-icon,.hero.is-warning a.header-item,.hero.is-warning .header-item>a:not(.button){color:rgba(0,0,0,0.5)}.hero.is-warning .header-icon:hover,.hero.is-warning .header-icon.is-active,.hero.is-warning a.header-item:hover,.hero.is-warning a.header-item.is-active,.hero.is-warning .header-item>a:not(.button):hover,.hero.is-warning .header-item>a:not(.button).is-active{color:rgba(0,0,0,0.5)}.hero.is-warning .tabs a{color:rgba(0,0,0,0.5);opacity:0.5}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.5)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background:rgba(0,0,0,0.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background:rgba(0,0,0,0.5);color:#fce473}.hero.is-warning.is-bold{background-image:-webkit-linear-gradient(309deg, #ffbd3d 0%, #fce473 71%, #fffe8a 100%);background-image:linear-gradient(141deg, #ffbd3d 0%, #fce473 71%, #fffe8a 100%)}@media screen and (max-width: 768px){.hero.is-warning .header-toggle span{background:rgba(0,0,0,0.5)}.hero.is-warning .header-toggle:hover{background:rgba(0,0,0,0.1)}.hero.is-warning .header-toggle.is-active span{background:rgba(0,0,0,0.5)}.hero.is-warning .header-menu .header-item{border-top-color:rgba(0,0,0,0.2)}}.hero.is-danger{background:#ed6c63;color:#fff}.hero.is-danger .title{color:#fff}.hero.is-danger .title a,.hero.is-danger .title strong{color:inherit}.hero.is-danger .subtitle{color:rgba(255,255,255,0.7)}.hero.is-danger .subtitle strong{color:#fff}.hero.is-danger .header .container{box-shadow:0 1px 0 rgba(255,255,255,0.2)}.hero.is-danger .header-icon,.hero.is-danger a.header-item,.hero.is-danger .header-item>a:not(.button){color:rgba(255,255,255,0.5)}.hero.is-danger .header-icon:hover,.hero.is-danger .header-icon.is-active,.hero.is-danger a.header-item:hover,.hero.is-danger a.header-item.is-active,.hero.is-danger .header-item>a:not(.button):hover,.hero.is-danger .header-item>a:not(.button).is-active{color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:0.5}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background:rgba(0,0,0,0.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background:#fff;color:#ed6c63}.hero.is-danger.is-bold{background-image:-webkit-linear-gradient(309deg, #f32a3e 0%, #ed6c63 71%, #f39376 100%);background-image:linear-gradient(141deg, #f32a3e 0%, #ed6c63 71%, #f39376 100%)}@media screen and (max-width: 768px){.hero.is-danger .header-toggle span{background:#fff}.hero.is-danger .header-toggle:hover{background:rgba(0,0,0,0.1)}.hero.is-danger .header-toggle.is-active span{background:#fff}.hero.is-danger .header-menu .header-item{border-top-color:rgba(255,255,255,0.2)}}@media screen and (min-width: 769px){.hero.is-fullheight .tabs,.hero.is-large .tabs{font-size:18px}}@media screen and (min-width: 769px){.hero.is-medium .hero-content{padding:120px 20px}}@media screen and (min-width: 980px){.hero.is-medium .hero-content{padding:120px 0}}.hero.is-large .tabs a{padding:10px 15px}@media screen and (min-width: 769px){.hero.is-large .hero-content{padding:240px 20px}}@media screen and (min-width: 980px){.hero.is-large .hero-content{padding:240px 0}}.hero.is-fullheight{-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;min-height:100vh}.hero.is-fullheight .tabs a{padding:15px 20px}.hero.is-fullheight .hero-content{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-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;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.hero.is-left{text-align:left}.hero.is-right{text-align:right}.section{background:white;padding:40px 20px}.section+.section{border-top:1px solid rgba(211,214,219,0.5)}@media screen and (min-width: 980px){.section{padding:40px 0}.section.is-medium{padding:120px 0}.section.is-large{padding:240px 0}}.footer{background:#f5f7fa;padding:40px 20px 80px}.footer a{color:#69707a}.footer a:hover{color:#222324}.footer a:not(.icon){border-bottom:1px solid #d3d6db}.footer a:not(.icon):hover{border-bottom-color:#1fc8db}
+/*# sourceMappingURL=bulma.min.css.map */
\ No newline at end of file
diff --git a/homie-esp8266-v1-setup-sources/app/vendor/font-awesome/icons.min.css b/homie-esp8266-v1-setup-sources/app/vendor/font-awesome/icons.min.css
new file mode 100644
index 0000000..f384095
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/app/vendor/font-awesome/icons.min.css
@@ -0,0 +1 @@
+@font-face{font-family:'FortAwesome';src:url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAA7kAA8AAAAAGfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABWAAAABsAAAAceQ+rm09TLzIAAAF0AAAARQAAAGAQ+ZFmY21hcAAAAbwAAABRAAABWuAdGx9jdnQgAAAILAAAAAsAAAAOAAAAAGZwZ20AAAg4AAAGPAAADRZ2ZHx0Z2FzcAAACCQAAAAIAAAACAAAABBnbHlmAAACEAAAA/cAAAYYwbvfm2hlYWQAAAYIAAAAMAAAADYKPbaJaGhlYQAABjgAAAAeAAAAJAgkBR1obXR4AAAGWAAAACcAAAAwJDQARmxvY2EAAAaAAAAAGQAAABoFkASObWF4cAAABpwAAAAgAAAAIADADf9uYW1lAAAGvAAAAR4AAAIfHNKRPHBvc3QAAAfcAAAASAAAAHJT8CZ3cHJlcAAADnQAAABtAAAAgicVCkB42mNgYGBkAIJLkRbnQfTlaMtUKJ0GAEGwBc0AeNpjYGHewTiBgZWBgamf6SADA0MvhGZ8zGDEyAIUZWBlZoABRgEGNNDAwPCBlTnhfwFDNHMCwwQglxFJVoGBEQBPjQr4AAAAeNpjYGBgZoBgGQZGBhAIAfIYwXwWBgsgzcXAwcAEhAwMvAwKH1j//werArEZgGzm/9//PxVgg+qFAkY2iJFgNkgnCwMqAKpmZRjeAACckwswAAAAeNqdVE1sG0UUnpndmdmdjXez9u46P07irO11sZ3EWTu7qEltpyUhSUVBrpecQBxAStKohx4qNap6CD1QFamVOKFKUQpC4oByqED0UIkLUg/lEIlG8pEDBy6lwAkJ6jJjagqlh8DO6pvve/tm5u28NwMQGAcAFtAukAAFyhdEhgCVixVz3MxXzMw4VH+4exftPnprHL0J+IMAeHxb+kkaADaY4P5HRnXM/WGFUEjcPHTzFb8OE44fJpJOzqKZvEcMKHkulTLeTDXwk4HvoP3PVLnzERtlnZtQ20/R/Bk1IM00g8HR/RrzyfJZJaTzPx699nBr6+E1mFalzh5j8LQ2vNO5MjQEzbr1c3P1ooOTv8DtoeHOb6vNi1e3tq524+P/s8bjGwWTPL6Ca0s8vpxtkcy46x2D1WAWzmR6zHdss+I7Ev9chE+NcM02Ot8Ztm1kswLbhs37Jdu4LhSHzSVBOLS7yL3v2OjCpmACAJDBAKCyiEMFI6ACFkCsweZnpsaSDAO5XMy63d1wbCt0J6GrQx5SNazxtZOORQK+lZPcRP9hF1YvTYmwBNm0nHTQSae5UF6YhcWl5ZeLkEWkdHn7colED1omfuXd6I3VpSpkLbxyv31/BX/Y6qf3Oql7tL+FN6AL+bobmJ7W4oODcW0xxZ9WHJemp0s43nrQwrNhIfsCH7LSbK7QKxG+dQtH/XT93Ll1CgD+qw4MMAamQB28CoxG38kTs5ViZjihSbhcDJ/Z1X9p8089Yz5fJ57R15myqbAutP8DDXqENT4XTMB7nTuCwpc47j/6XnCU4ggHfv9aCGmOoyglwv/zgvyitMpPhwGS4AzYBQfAbOhffrx9tlVw4jojiJSLoOq5xHJ8+Ukff9JT2zIgoY6lQ3eKE96Kgnl5nsdJuVqDoccV35I6DEKPa3+ME95mBXOSYeCPynw0dYQKQt/xLcqLYQRaVMwrZsy4eV4aJJN3q6GXF5OFYi4/7B63xP8ZBH+NzkfReYQLc4XeuxdbpVqYOG7i+fggJXJszUAxxzquqGrScnTiqTqO9Oc7nSDs7043SxpuSCMaabWINoIks4xomTikTBdRzyolJvqE7fCucELEHO1140Ub3e4Tsb7tLPQNzmOfKceGYvrrCqvIPDEDcaZMx0b7Y8g4jNO3c/IRnnhDYac0auiLDEGWakDY6FmZYugNUxtpQFQ/vK+4s2KPt6VP+VmioCju1DhB6GlJhRbPlgFFHYnCqUNROl0SVHjKalBcYIV0KZ0u7URv55Y1tU1UmqXS1M4NyGiW0UuYHdRyG199oGjolPBLt9//5p1c7YDhSwhnVfXGzhTEWdbXVrXl3PprGvgDV5j7QAB42mNgZGBgAOLznZVy8fw2Xxm4mT8ARRguR1umIej/lSwZzOFALgcDE0gUADWbCnF42mNgZGBgTmCYwBDN0sAABCwZDIwMqIAHADs9Ak0AAHjaY8xhUGQAAsYABgbmD6iYMYOBgaWBQQLEZrEAiq1g4AUAs3IHmAB42mNgYJBAghkMaxhlGCcwHWLmAQAawAMmAAAAAAEAAAAMANYABgAAAAAAAgAAABEAiwAAACINFgAAAAB42nWPMU+DQBiGX1qoMRrHamJibrMdIBwNHdqlHexoTIcuTgyUkrScgaMd/Bn+ChdX/54v3CViUiFv7vm+7+GOA3CDLzgwzzVj2MEVK8M9XODWch+PeLDs0nmy7EHgxfKA/TeajnvJ6g7vlh0M8WG5x3M/LffxjG/LLoaOZ9nDwrm3PGD/daVKLZantFKHtGGL6zSr90m5UoVmN0tFFIRiJjoGKznxYz8K5bTT3qRllatCSPpzofU2qbXa5YUWo6MM4nFHxQoKJTSvucQJKSrWB/z2/3bXTIYaeyScNk5Bx7gZZwIRAoRcZ8z5PcxMYgIfMRPRl5j+Y2+YklXentV8Z/afM5rvln9Sc1XY0Snam4xwbL0Y4/O7/gDQ0luCAAB42mNgYgCD/00MRgzYAA8QMzIwMTIxMjMwM7IwsjKyMbIzcjBysviF+vgwOQexl+ZluhkYGEBpQyhtBKWNobQJlDYFAGghENcAAQAB//8AD3jaY2BABgAADgABAHjarVZpd9NGFJW8ZSMbWWhRS8dMnKbRyKQUggEDQYrtQro4WytBaaU4SfcFutF9X/CveXLac+g3flrvG9kmgYSe9tQf9O7MuzNvm3ljMpQgY92vBEIs3TWGlpcot3rNp1MWzQThtmiu+5QqRH/1Gr1GoyE3rHyejIAMTy62DNPwQtchU5EItx1KKbEp6F6dMtPXWjNmv1dpVChX8fOULgQr1/28zFtNX1C9jqmFwBJUYlQKAhEn7GiTZjDVHgmaY/0cM+/VfQFvmpGg/rofYkawrp/RPKP50AqDILDItINAklH3t4LAobQS2CdTiOBZ1qv7lJUu5aSLOAIyQ4cySsIvsRlnN1zBGvbYSjzgLxlhpUHp2TyUnmiKJgzEc9kCglz2w7oVrQS+DPKBoIVVHzqLQ2vbdyirqMezW0YqyVQOQ+lKZFy6EaU2tslswAvKzjrUowS7OuA17maMDcE70EIYMCVc1K72qlbPgOFV3Nl8N/d9am8t+pNdTBsueIg7FJWmjLguOl+GxTklYcHJjpeojowWExMDByynKawyrPuh7V50SOmAWgP9aRTbkvlgNu/QoIpTqQptRosODSkQhaBD3lVeDiDdgAZ5tILRIEYODWObEZ0SgQw0YJeGvFA0Q0FDSJpDI2ppzY8zm4vBFA1uydsOjaqlZX9pNZm08pgf0/OHVWwMe+t+PDzskRm5NGzzmcVJduND/BnEh8xJVCJdqPsxJw/Ruk3Ul83O5iWWdbCV6HkJrgLPBIikBv9rmN1bqgMKGBvGmES2cJwutkzT1LUaU0ZspCprPg1LV1RoAIevH/kNXRHC/J+jo6YxZLhuM4wP52y6Y1vHkaZxxDZmOzShYpPlJPLM8oiK0ywfU3GG5eMqzrI8quIcS0vFPSyfUHEvyydV3MfyGSU7eadciAxLUSTzBl8Qh2Z3KSe7ypuJ0t6lnO4qbyXKY8qgQfs/xPcU4jsGvwTiY5lHfCyPIz6WEvGxnEJ8LAuIj+U04mP5NOJjOYP4WColyvqYOgpmR0Phobahp0uJq6f4rBYVOTY5uIUncAFq4oAqyqgkuSM+kmFx9HPd0pqTdGI2zpoTFR+NjAN8dndmHlafVOK09vc58MzKw0ZwO/c1zvPG5B8G/xYvylJ80pzg4E4hAfB4f4dxK6KSQ6dV8UjZofl/ouIEN0A/g5oYkwVRFDW++cjllWazJmtoFT6eCHRWtIN505wYR0pLaFGTNAJaBl2zoGnU59lbzaIUotzEfmf3UkQx2YsymAFTUMhNY2HZ30mJtLB2UtPpo4HLjbQXPVlqtqziCnsP3seQm1nybqS8cFNS2os2oU55kQUcciN7cE0Et9DeZRXFlLBQRXwQ2gr228eITFpmBl0CRcjiZGUf2hU7ckQF7QS+9aRV3reF2p/r5EFgNjvdzoMsI0Xnuyrq1fqqrLFRrl65mz4Opp1hY80vijKeXPa+PSnYr04JcgWMrux+3ZPi7Xes25WSfLYv7PLE65Qq5L8AD4bcKe9FNIoiZ7FKI55ft/BkinJQjIvmOC7opT3aFau+R7uw79pHrbisqGQ/yqCr6KzdhG98vhDUgVQUtEhFrPB0yHw2OzXhYylxWYq4Z8mui+g7eEI6xH9xiGv/17nlKLhFlSW60K4Tkg/aPlbQW0t2Jw9VjM7aednORDuSbtA1BD2RXHD8vcBdHivSKdzn5w+Yv4LtzPExOg18VdEZiCXOWwUJFlW8pZ1MvaD4CNMS4IuqhWYF8BKAyeBl1TL1TB1AzywzpwKwwhwGq8xhsMYcButqB13vMtArQKZGr6odM5nzgZK5gHkmo2vM0+g68zR6jXka3WCbHsDrbJPBG2yTQcg2GUTMqQJsMIdBgzkMNpnDYEv75QJta78Yvan9YvSW9ovR29ovRu9ovxi9q/1i9J72i9H7yPG5bgE/0CO6CPhhAi8BfsRJ16MFjG7iGW1zbiWQOR9rjtnmfILF57u7fqpHesVnCeQVnyeQ6bexT5vwRQKZ8GUCmfAVuOXufl/rkaZ/k0Cmf5tApn+HlW3C9wlkwg8JZMKP4F7o7veTHmn6zwlk+i8JZPqvWNkm/JZAJvyeQCbcUTt9mVTnz6prU+8WpafqtzvvsPM3Rxm6KXjaY/DewXAiKGIjI2Nf5AbGnRwMHAzJBRsZ2J02MjBoQWgOFHonAwMDJzKLmcFlowpjR2DEBoeOiI3MKS4b1UC8XRwNDIwsDh3JIREgJZFAsJGBR2sH4//WDSy9G5kYXDazprAxuLgAAAZPJGwAAAA=) format("woff");font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FortAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-heartbeat:before{content:'\f000'}.fa-info:before{content:'\f001'}.fa-wifi:before{content:'\f002'}.fa-signal:before{content:'\f003'}.fa-cogs:before{content:'\f004'}.fa-rocket:before{content:'\f005'}
diff --git a/homie-esp8266-v1-setup-sources/gulpfile.babel.js b/homie-esp8266-v1-setup-sources/gulpfile.babel.js
new file mode 100644
index 0000000..e8e17bb
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/gulpfile.babel.js
@@ -0,0 +1,163 @@
+'use strict';
+
+import gulp from 'gulp';
+import plumber from 'gulp-plumber'; // help to avoid crash if error in a task
+import newer from 'gulp-newer';
+import watch from 'gulp-watch'; // gulp.watch doesn't detect new files
+import smoosher from 'gulp-smoosher';
+import zopfli from 'gulp-zopfli';
+import rename from 'gulp-rename';
+import del from 'del'; // delete files
+import imagemin from 'gulp-imagemin';
+import runSequence from 'run-sequence';
+import notifier from 'node-notifier';
+import uglify from 'gulp-uglify';
+import browserify from 'browserify';
+import envify from 'envify/custom';
+import babelify from 'babelify';
+import source from 'vinyl-source-stream'; // helper for browserify text stream to gulp pipeline
+import buffer from 'vinyl-buffer'; // helper for browserify
+
+let errored = false;
+let errorHandler = function (task) {
+ return function (error) {
+ errored = true;
+ console.log(`Error in ${task}: ${error.message}`);
+ notifier.notify({
+ title: `Error in ${task}`,
+ message: error.message
+ });
+ };
+};
+
+// ################
+// # Entry points #
+// ################
+
+gulp.task('dev', ['buildpublic:dev'], function (done) {
+ watch('./app/assets/**/*', function (vinyl) {
+ console.log(`${vinyl.path} was ${vinyl.event}, piping to public/...`);
+ runSequence('assets');
+ });
+
+ watch('./app/vendor/**/*', function (vinyl) {
+ console.log(`${vinyl.path} was ${vinyl.event}, piping to public/vendor/...`);
+ runSequence('vendor');
+ });
+
+ watch('./app/js/**/*.js', function (vinyl) {
+ console.log(`${vinyl.path} was '${vinyl.event}', running Babel...`);
+ runSequence('es6-7:dev');
+ });
+});
+
+gulp.task('dist', function (done) {
+ runSequence('buildpublic:dist', 'builduigz', function () {
+ if (errored) {
+ console.log('Distribution failed');
+ process.exit(-1);
+ }
+
+ done();
+ });
+});
+
+// ####################
+// # public directory #
+// ####################
+
+gulp.task('builduigz', function () {
+ return gulp.src('index.html')
+ .pipe(plumber(errorHandler('buildpublic:imagemin')))
+ .pipe(smoosher())
+ .pipe(rename('ui_bundle'))
+ .pipe(zopfli())
+ .pipe(gulp.dest('./'));
+});
+
+gulp.task('buildpublic:dist', function (done) {
+ runSequence(
+ 'buildpublic:clear',
+ ['assets', 'vendor', 'es6-7:dist'],
+ 'buildpublic:imagemin',
+ done);
+});
+
+gulp.task('buildpublic:dev', function (done) {
+ runSequence(
+ 'buildpublic:clear',
+ ['assets', 'vendor', 'es6-7:dev'],
+ done);
+});
+
+gulp.task('buildpublic:clear', function (done) {
+ del(['./public/**/*']).then(function () {
+ done();
+ });
+});
+
+gulp.task('buildpublic:imagemin', function () {
+ return gulp.src('./public/img/**/*.{png,jpg,gif,svg}', {
+ base: './public'
+ })
+ .pipe(plumber(errorHandler('buildpublic:imagemin')))
+ .pipe(imagemin({
+ progressive: true
+ }))
+ .pipe(gulp.dest('./public'));
+});
+
+// Babel
+
+let es67 = (prod = false) => {
+ const babelPlugins = [];
+ if (prod) babelPlugins.push(['module-alias', [{ 'src': 'npm:preact-compat', 'expose': 'react' }, { 'src': 'npm:preact-compat', 'expose': 'react-dom' }]]);
+ return browserify({ entries: './app/js/app.js', debug: false }) // debug for sourcemaps
+ .transform(babelify, { presets: ['es2015', 'stage-3', 'react'], plugins: babelPlugins });
+};
+
+gulp.task('es6-7:dev', function () {
+ return es67()
+ .bundle()
+ .on('error', function (error) {
+ errorHandler('es6-7')(error);
+ this.emit('end');
+ }) // Don't crash if failed, plumber doesn't work with browserify
+ .pipe(source('bundle.min.js'))
+ .pipe(buffer())
+ .pipe(gulp.dest('./public/js'));
+});
+
+gulp.task('es6-7:dist', function () {
+ return es67(true)
+ .transform(envify({ NODE_ENV: 'production' }), { global: true }) // global: act on node_modules (here react prod mode)
+ .bundle()
+ .on('error', function (error) {
+ errorHandler('es6-7')(error);
+ this.emit('end');
+ }) // Don't crash if failed, plumber doesn't work with browserify
+ .pipe(source('bundle.min.js'))
+ .pipe(buffer())
+ .pipe(uglify())
+ .pipe(gulp.dest('./public/js/'));
+});
+
+// assets and vendor
+
+gulp.task('assets', function () {
+ return gulp.src('./app/assets/**/*', {
+ base: './app/assets'
+ })
+ .pipe(plumber(errorHandler('assets')))
+ .pipe(newer('./public'))
+ .pipe(gulp.dest('./public'));
+});
+
+gulp.task('vendor', function () {
+ return gulp.src('./app/vendor/**/*', {
+ base: './app'
+ })
+ .pipe(plumber(errorHandler('vendor')))
+ .pipe(newer('./public'))
+ .pipe(gulp.dest('./public'));
+});
diff --git a/homie-esp8266-v1-setup-sources/index.html b/homie-esp8266-v1-setup-sources/index.html
new file mode 100644
index 0000000..3cbf2f2
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/index.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+ Set up your Homie for ESP8266 device
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/homie-esp8266-v1-setup-sources/package.json b/homie-esp8266-v1-setup-sources/package.json
new file mode 100644
index 0000000..dd7a23c
--- /dev/null
+++ b/homie-esp8266-v1-setup-sources/package.json
@@ -0,0 +1,55 @@
+{
+ "name": "homie-esp8266-configurator",
+ "version": "0.1.0",
+ "description": "UI to configure an ESP8266 loaded with an Homie firmware",
+ "scripts": {
+ "dev": "gulp dev",
+ "dist": "gulp dist"
+ },
+ "author": {
+ "name": "Marvin Roger",
+ "email": "bonjourmarvin@marvinroger.fr",
+ "url": "http://marvinroger.fr"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/marvinroger/homie-esp8266-configurator.git"
+ },
+ "bugs": "https://github.com/marvinroger/homie-esp8266-configurator/issues",
+ "homepage": "https://github.com/marvinroger/homie-esp8266-configurator",
+ "license": "GPL-2.0",
+ "dependencies": {
+ "babel-runtime": "^6.3.19"
+ },
+ "devDependencies": {
+ "babel-core": "^6.4.0",
+ "babel-plugin-module-alias": "^1.4.0",
+ "babel-plugin-transform-runtime": "^6.3.13",
+ "babel-preset-es2015": "^6.1.18",
+ "babel-preset-react": "^6.1.18",
+ "babel-preset-stage-3": "^6.1.18",
+ "babelify": "^7.2.0",
+ "browserify": "^13.0.0",
+ "del": "^2.2.0",
+ "envify": "^3.4.0",
+ "gulp": "^3.9.0",
+ "gulp-imagemin": "^2.4.0",
+ "gulp-newer": "^1.1.0",
+ "gulp-plumber": "^1.0.1",
+ "gulp-rename": "^1.2.2",
+ "gulp-smoosher": "0.0.9",
+ "gulp-uglify": "^1.5.1",
+ "gulp-watch": "^4.3.5",
+ "gulp-zopfli": "^1.0.0",
+ "immutable": "^3.7.6",
+ "node-notifier": "^4.3.1",
+ "preact-compat": "^1.7.1",
+ "react": "^15.0.1",
+ "react-dom": "^15.0.1",
+ "request": "^2.67.0",
+ "run-sequence": "^1.1.5",
+ "vinyl-buffer": "^1.0.0",
+ "vinyl-source-stream": "^1.1.0",
+ "whatwg-fetch": "^0.11.0"
+ }
+}
diff --git a/pixelprojektor/pixelprojektor.ino b/pixelprojektor/pixelprojektor.ino
index 72b9dfd..311fb12 100644
--- a/pixelprojektor/pixelprojektor.ino
+++ b/pixelprojektor/pixelprojektor.ino
@@ -1,24 +1,50 @@
-#include
-
+#include
// homie lib from: https://github.com/marvinroger/homie-esp8266/
+#include
+#ifdef __AVR__
+ #include
+#endif
+#define PIN 2 //data pin for ws2812
-HomieNode effectNode("effect", "commands");
-HomieNode pixelsNode("pixels", "commands");
+Adafruit_NeoPixel strip = Adafruit_NeoPixel(64, PIN, NEO_GRB + NEO_KHZ800);
+HomieNode homieNode("pixel", "commands");
+
+void led_fill(uint32_t c)
+{
+ for (int i=0; i < strip.numPixels(); i++) {
+ strip.setPixelColor(i, c); //turn every third pixel on
+ }
+ strip.show();
+}
bool effectHandler(const HomieRange& range, const String& value) {
int sep = value.indexOf("|");
- if(sep > 0) {
- //Homie.getLogger() << "scroll " << value << " wait " << wait << endl;
-
- } else {
+ Homie.getLogger() << "-> " << value << endl;
+
+ //Serial.print("->"); Serial.println(value);
+
+ if (value.charAt(0)=='#'){ //solid fill
+ String color=value.substring(1);
+ int number = (int) strtol( &color[0], NULL, 16);
- //Homie.getLogger() << "scroll " << value << endl;
+
+ // Split them up into r, g, b values
+ int r = number >> 16;
+ int g = number >> 8 & 0xFF;
+ int b = number & 0xFF;
+ Homie.getLogger() << "r=" << r << " g=" << g << " b=" << b << endl;
+ //Serial.print("r=");Serial.print(r);
+ //Serial.print(" g=");Serial.print(g);
+ //Serial.print(" b=");Serial.println(b);
+
+ led_fill(strip.Color(r, g, b));
}
+
return true;
}
@@ -46,11 +72,17 @@ void setup() {
Homie_setFirmware("pixelprojektor", "1.0.0");
- effectNode.advertise("on").settable(effectHandler);
- pixelsNode.advertise("on").settable(pixelsHandler);
+ homieNode.advertise("effect").settable(effectHandler);
+ homieNode.advertise("pixels").settable(pixelsHandler);
+ strip.begin();
+ strip.show(); // Initialize all pixels to 'off'
+
+ led_fill(strip.Color(0, 0, 0));
Homie.setup();
+
+
}
void loop() {
@@ -61,3 +93,6 @@ void loop() {
+
+
+