Page MenuHomePhabricator

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.gitignore b/.gitignore
index 58539e9..3e0685f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
-Documentation/*
*.*~
*.DS_STORE
-*.sublime-project
-
-*.sublime-workspace
+/nbproject/private/
+/bin/settings/environments.php
+/vendor/
diff --git a/.gitmodules b/.gitmodules
index 615ef33..6785d17 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,9 @@
[submodule "Spitfire"]
path = spitfire
url = https://github.com/Csardelacal/SpitfireEngine.git
+[submodule "m3js"]
+ path = assets/js/m3
+ url = https://github.com/Csardelacal/m3.js.git
+[submodule "_SCSS"]
+ path = assets/scss/_
+ url = https://github.com/Csardelacal/underscoreSCSS.git
diff --git a/assets/css/app.css b/assets/css/app.css
new file mode 100644
index 0000000..59ee0b6
--- /dev/null
+++ b/assets/css/app.css
@@ -0,0 +1,2507 @@
+@charset "UTF-8";
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : 02-jun-2015, 21:46:57
+ Author : cesaradelacalbretschneider
+*/
+* {
+ box-sizing: border-box; }
+
+body {
+ margin: 0;
+ font-family: sans-serif;
+ background-color: #FAFAFA; }
+
+.hidden {
+ display: none !important; }
+
+/*
+ * Disabled items should be unable to receive mouse pointer events. When clicked
+ * or interacted with, these items should be unresponsive.
+ */
+:disabled, .disabled, [disabled] {
+ pointer-events: none; }
+
+a {
+ color: #555;
+ text-decoration: none; }
+ a:hover {
+ color: #333; }
+ a.highlighted {
+ color: #2a912e; }
+ a.highlighted:hover {
+ color: #2a912e; }
+ a.heavy {
+ font-weight: bold; }
+ a img {
+ border: none; }
+
+h1 {
+ font-size: 20px;
+ color: #2a912e;
+ font-weight: normal;
+ background: #FAFAFA; }
+ h1.unpadded {
+ margin: 0;
+ padding: 0; }
+
+h2 {
+ color: #353535;
+ font-size: 18px; }
+
+p {
+ color: #555;
+ line-height: 1.6em; }
+ p.unpadded {
+ margin: 0; }
+ p.small {
+ font-size: .78em; }
+ p.secondary {
+ color: #777; }
+ p.secondary a {
+ color: #333; }
+
+blockquote {
+ margin-left: 0;
+ padding: 15px 5px 15px 15px;
+ border-left: solid 3px #AAA;
+ background: #F9F9F9;
+ color: #555;
+ font-size: .9em; }
+
+table {
+ width: 100%;
+ border-radius: 3px;
+ border-collapse: collapse;
+ font-size: .85em; }
+ table thead tr {
+ box-shadow: 1px 1px 2px #CCC; }
+ table thead tr th {
+ border-bottom: solid 1px #AAA;
+ background: #888;
+ color: #FFF; }
+ table thead tr th:first-child {
+ border-radius: 2px 0px 0 0; }
+ table thead tr th:last-child {
+ border-radius: 0px 2px 0 0; }
+ table tr {
+ background: #FFF;
+ border-top: solid 1px #EEE; }
+ table tr:first-child {
+ border-top: none; }
+ table tr:nth-child(2n) {
+ background: #FAFAFA; }
+ table td, table th {
+ margin: 0;
+ padding: 8px 20px; }
+
+form.regular .field {
+ display: block;
+ box-sizing: border-box; }
+ form.regular .field label {
+ display: block;
+ font-size: .9em;
+ color: #555;
+ width: 100%; }
+ form.regular .field input[type=text],
+ form.regular .field input[type=email],
+ form.regular .field input[type=password],
+ form.regular .field textarea,
+ form.regular .field select {
+ width: 100%;
+ padding: 5px 10px;
+ font-size: 1.05em;
+ background: #FFF;
+ border: solid 1px #EEE;
+ box-sizing: border-box;
+ height: 2em; }
+ form.regular .field input[type=text].borderless,
+ form.regular .field input[type=email].borderless,
+ form.regular .field input[type=password].borderless,
+ form.regular .field textarea.borderless,
+ form.regular .field select.borderless {
+ border: none; }
+ form.regular .field input[type=text]:focus,
+ form.regular .field input[type=email]:focus,
+ form.regular .field input[type=password]:focus,
+ form.regular .field textarea:focus,
+ form.regular .field select:focus {
+ outline: none; }
+ form.regular .field textarea {
+ height: 150px; }
+form.regular .form-footer {
+ padding-top: 15px;
+ padding-right: 10px;
+ margin-top: 15px;
+ text-align: right; }
+ form.regular .form-footer * {
+ vertical-align: middle; }
+ form.regular .form-footer a {
+ font-size: .8em; }
+form.regular input[type="submit"] {
+ margin-left: 15px;
+ font-family: sans-serif; }
+
+.material-form input[type="text"], .material-form .fake-field, .material-form .fake-field-ph {
+ display: inline-block;
+ padding: 3px 6px;
+ max-width: 95%;
+ overflow: hidden;
+ text-overflow: ellipsis; }
+.material-form .fake-field-ph {
+ border: 1px solid transparent; }
+.material-form input[type="text"], .material-form .fake-field {
+ border: 1px solid grey;
+ background: #fff;
+ font-size: 16px;
+ font-family: inherit;
+ vertical-align: baseline; }
+.material-form .fake-field {
+ user-select: all; }
+
+.no-selection {
+ user-select: none; }
+
+.button, form.regular input[type="submit"] {
+ background: #3191f1;
+ box-shadow: -2px -2px 1px #3167f1 inset;
+ border: none;
+ border-radius: 3px;
+ color: #ffffff;
+ font-weight: bold;
+ padding: .7em 1.2em;
+ cursor: pointer;
+ text-decoration: none;
+ display: inline-block; }
+ .button:disabled, form.regular input[type="submit"]:disabled {
+ background-color: #094580;
+ box-shadow: -2px -2px 1px #092a80 inset;
+ cursor: not-allowed; }
+ .button.error, form.regular input.error[type="submit"] {
+ background: #f13131;
+ box-shadow: -2px -2px 1px #803709 inset; }
+ .button.success, form.regular input.success[type="submit"] {
+ background: #0cb027;
+ box-shadow: -2px -2px 1px #055116 inset; }
+ .button.small, form.regular input.small[type="submit"] {
+ padding: .35em .5em;
+ font-size: .78em; }
+ .button.secondary, form.regular input.secondary[type="submit"] {
+ color: #777; }
+ .button:hover, form.regular input[type="submit"]:hover {
+ color: #FFF; }
+
+.menubar {
+ background: #FEFEFE;
+ vertical-align: top;
+ text-align: right;
+ box-shadow: 0 2px 2px #DDD;
+ border-bottom: solid 1px #CCC;
+ z-index: 5; }
+ .menubar a {
+ display: inline-block;
+ text-decoration: none;
+ color: #333;
+ padding: 10px 15px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box; }
+ .menubar a:hover {
+ text-shadow: 0 0 4px #DDD; }
+ .menubar .logo {
+ display: inline-block;
+ float: left;
+ border: none; }
+
+.badge {
+ width: 100%;
+ padding: .5em;
+ box-shadow: -2px 2px 2px #EAEAEA inset;
+ background: #FAFAFA;
+ border: solid 1px #CCC;
+ display: block;
+ border-radius: 3px; }
+
+footer {
+ background: #FFF;
+ color: #555;
+ text-align: center;
+ padding: 5px;
+ line-height: 20px;
+ font-size: 12px;
+ border-top: solid 1px #CCC; }
+
+.material {
+ background: #FFF;
+ box-shadow: 1px 1px 1px #DDD;
+ border-radius: 2px;
+ border: solid 1px #CCC;
+ padding: 20px 15px 15px; }
+ .material.unpadded {
+ padding: 0; }
+ .material .padded {
+ padding: 20px 15px 15px; }
+ .material .inset {
+ color: #FFF;
+ background: #888;
+ box-shadow: inset 1px 1px 2px #666; }
+ .material .inset p, .material .inset a {
+ color: #FFF; }
+ .material .inset:last-child {
+ border-radius: 0 0 2px 2px; }
+
+.login-logo {
+ text-align: center; }
+ .login-logo img {
+ max-width: 500px; }
+
+.extra-small.user-icon, .extra-small.app-icon {
+ width: 24px;
+ height: 24px; }
+.small.user-icon, .small.app-icon {
+ width: 32px;
+ height: 32px; }
+.medium.user-icon, .medium.app-icon {
+ width: 64px;
+ height: 64px; }
+.big.user-icon, .big.app-icon {
+ width: 128px;
+ height: 128px; }
+.huge.user-icon, .huge.app-icon {
+ width: 256px;
+ height: 256px; }
+.full-width.user-icon, .full-width.app-icon {
+ max-width: 100%; }
+
+.user-name {
+ vertical-align: middle;
+ display: inline-block;
+ font-size: 1.2em;
+ color: #333;
+ text-decoration: none; }
+
+.user-icon {
+ border-radius: 50%;
+ display: inline-block;
+ vertical-align: middle;
+ border: solid 2px #FFF; }
+ .user-icon.square {
+ border-radius: 10px; }
+
+.app-name {
+ vertical-align: middle;
+ display: inline-block;
+ font-size: 1em;
+ color: #333;
+ text-decoration: none; }
+
+.app-icon {
+ border-radius: 3px;
+ border-radius: 3px;
+ box-shadow: 0 0 2px #CCC;
+ vertical-align: middle; }
+ .app-icon + .app-name {
+ margin-left: .4em; }
+
+.validation-errors {
+ color: #900;
+ list-style: none;
+ font-size: .9em;
+ margin: 10px 0;
+ padding: 0; }
+ .validation-errors li {
+ border-left: solid 2px #900;
+ padding-left: 10px;
+ margin-top: 8px; }
+ .validation-errors .error-message {
+ font-weight: bold;
+ display: block; }
+ .validation-errors .extended-message {
+ font-size: .9em; }
+
+.heading {
+ display: block;
+ padding: 10px 5px;
+ color: #FFF;
+ font-weight: bold;
+ color: #2a912e;
+ border-bottom: solid 1px #2a912e;
+ background: #FAFAFA; }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Dec 9, 2019, 4:25:00 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : 24.10.2018, 16:26:42
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+
+ The purpose of this software is to provide a series of minimal standard
+ components that are typical among UIs and that are required almost universally
+ by web applications. These include resetting, scaffolding, basic form elements,
+ basic text formatting elements, basic navigation bars and footers.
+
+ Some of these functions will require appropriate Javascript to be used.
+ This requires the use of a _.scss.js file that will provide the required
+ functionality. This file will be provided with compatibility for m3.js's
+ dependency loader.
+
+ The use of the Javascript component MUST be optional and allow for graceful
+ fallbacks while the JS is either not loaded, or failed loading.
+*/
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Aug 20, 2019, 5:06:55 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+html {
+ /*
+ * Resets the system to use a known good system font.
+ * See: https://furbo.org/2018/03/28/system-fonts-in-css/
+ */
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; }
+
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : 20.04.2018, 16:35:00
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : 20.04.2018, 14:51:25
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.span {
+ display: inline-block;
+ vertical-align: top;
+ min-height: 1px;
+ font-size: 16px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ padding: 3px 1.0416666667%;
+ width: 100%; }
+
+div.row {
+ display: block;
+ margin: 0 auto;
+ width: 100%;
+ /*
+ * Fixes an issue that browsers will have rendering the layout. Since the system
+ * does use inline-block, spaces that are parsed from the HTML file (due to tabs
+ * or spaces being present to indent the file) will cause the blocks to separate
+ * just a tiny bit and cause the layout to break.
+ */
+ font-size: 0;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box; }
+ div.row.fluid {
+ width: 100%;
+ max-width: 100%; }
+ div.row.ng .span {
+ padding: 0; }
+ div.row.ng-lr .span:first-child {
+ padding-left: 0; }
+ div.row.ng-lr .span:nth-last-of-type(1) {
+ padding-right: 0; }
+
+/*
+This are the functions (mixins) used to generate the basic scaffolding for our
+website. Due to the inverted functionality of the grid we rewrote big parts to
+make them more usable.
+*/
+/*!
+ Created on : Oct 26, 2013, 7:18:16 PM
+ Author : cesar
+*/
+._fs1-s1, .row.s2 > .span.s2, .row.s3 > .span.s3, .row.s4 > .span.s4, .row.s5 > .span.s5, .row.s6 > .span.s6, .row.s7 > .span.s7, .row.s8 > .span.s8, .row.s9 > .span.s9, .row.s10 > .span.s10,
+.row.s1 > .span.s1 {
+ width: 100%; }
+
+._fs2-s1, .row.s4 > .span.s2, .row.s6 > .span.s3, .row.s8 > .span.s4, .row.s10 > .span.s5,
+.row.s2 > .span.s1 {
+ width: 50%; }
+
+._fs3-s1, .row.s6 > .span.s2, .row.s9 > .span.s3,
+.row.s3 > .span.s1 {
+ width: 33.3333333333%; }
+
+._fs3-s2, .row.s6 > .span.s4, .row.s9 > .span.s6,
+.row.s3 > .span.s2 {
+ width: 66.6666666667%; }
+
+._fs4-s1, .row.s8 > .span.s2,
+.row.s4 > .span.s1 {
+ width: 25%; }
+
+._fs4-s3, .row.s8 > .span.s6,
+.row.s4 > .span.s3 {
+ width: 75%; }
+
+._fs5-s1, .row.s10 > .span.s2,
+.row.s5 > .span.s1 {
+ width: 20%; }
+
+._fs5-s2, .row.s10 > .span.s4,
+.row.s5 > .span.s2 {
+ width: 40%; }
+
+._fs5-s3, .row.s10 > .span.s6,
+.row.s5 > .span.s3 {
+ width: 60%; }
+
+._fs5-s4, .row.s10 > .span.s8,
+.row.s5 > .span.s4 {
+ width: 80%; }
+
+._fs6-s1,
+.row.s6 > .span.s1 {
+ width: 16.6666666667%; }
+
+._fs6-s5,
+.row.s6 > .span.s5 {
+ width: 83.3333333333%; }
+
+._fs7-s1,
+.row.s7 > .span.s1 {
+ width: 14.2857142857%; }
+
+._fs7-s2,
+.row.s7 > .span.s2 {
+ width: 28.5714285714%; }
+
+._fs7-s3,
+.row.s7 > .span.s3 {
+ width: 42.8571428571%; }
+
+._fs7-s4,
+.row.s7 > .span.s4 {
+ width: 57.1428571429%; }
+
+._fs7-s5,
+.row.s7 > .span.s5 {
+ width: 71.4285714286%; }
+
+._fs7-s6,
+.row.s7 > .span.s6 {
+ width: 85.7142857143%; }
+
+._fs8-s1,
+.row.s8 > .span.s1 {
+ width: 12.5%; }
+
+._fs8-s3,
+.row.s8 > .span.s3 {
+ width: 37.5%; }
+
+._fs8-s5,
+.row.s8 > .span.s5 {
+ width: 62.5%; }
+
+._fs8-s7,
+.row.s8 > .span.s7 {
+ width: 87.5%; }
+
+._fs9-s1,
+.row.s9 > .span.s1 {
+ width: 11.1111111111%; }
+
+._fs9-s2,
+.row.s9 > .span.s2 {
+ width: 22.2222222222%; }
+
+._fs9-s4,
+.row.s9 > .span.s4 {
+ width: 44.4444444444%; }
+
+._fs9-s5,
+.row.s9 > .span.s5 {
+ width: 55.5555555556%; }
+
+._fs9-s7,
+.row.s9 > .span.s7 {
+ width: 77.7777777778%; }
+
+._fs9-s8,
+.row.s9 > .span.s8 {
+ width: 88.8888888889%; }
+
+._fs10-s1,
+.row.s10 > .span.s1 {
+ width: 10%; }
+
+._fs10-s3,
+.row.s10 > .span.s3 {
+ width: 30%; }
+
+._fs10-s7,
+.row.s10 > .span.s7 {
+ width: 70%; }
+
+._fs10-s9,
+.row.s10 > .span.s9 {
+ width: 90%; }
+
+@media all and (max-width: 960px) and (min-width: 480px) {
+ .desktop-only {
+ display: none !important; }
+
+ .mobile-only {
+ display: none; }
+
+ .not-tablet {
+ display: none; }
+
+ /*
+ This are the functions (mixins) used to generate the basic scaffolding for our
+ website. Due to the inverted functionality of the grid we rewrote big parts to
+ make them more usable.
+ */
+ /*!
+ Created on : Oct 26, 2013, 7:18:16 PM
+ Author : cesar
+ */
+ ._fm1-m1, .row.m2 > .span.m2, .row.m3 > .span.m3, .row.m4 > .span.m4, .row.m5 > .span.m5, .row.m6 > .span.m6, .row.m7 > .span.m7, .row.m8 > .span.m8, .row.m9 > .span.m9, .row.m10 > .span.m10,
+ .row.m1 > .span.m1 {
+ width: 100%; }
+
+ ._fm2-m1, .row.m4 > .span.m2, .row.m6 > .span.m3, .row.m8 > .span.m4, .row.m10 > .span.m5,
+ .row.m2 > .span.m1 {
+ width: 50%; }
+
+ ._fm3-m1, .row.m6 > .span.m2, .row.m9 > .span.m3,
+ .row.m3 > .span.m1 {
+ width: 33.3333333333%; }
+
+ ._fm3-m2, .row.m6 > .span.m4, .row.m9 > .span.m6,
+ .row.m3 > .span.m2 {
+ width: 66.6666666667%; }
+
+ ._fm4-m1, .row.m8 > .span.m2,
+ .row.m4 > .span.m1 {
+ width: 25%; }
+
+ ._fm4-m3, .row.m8 > .span.m6,
+ .row.m4 > .span.m3 {
+ width: 75%; }
+
+ ._fm5-m1, .row.m10 > .span.m2,
+ .row.m5 > .span.m1 {
+ width: 20%; }
+
+ ._fm5-m2, .row.m10 > .span.m4,
+ .row.m5 > .span.m2 {
+ width: 40%; }
+
+ ._fm5-m3, .row.m10 > .span.m6,
+ .row.m5 > .span.m3 {
+ width: 60%; }
+
+ ._fm5-m4, .row.m10 > .span.m8,
+ .row.m5 > .span.m4 {
+ width: 80%; }
+
+ ._fm6-m1,
+ .row.m6 > .span.m1 {
+ width: 16.6666666667%; }
+
+ ._fm6-m5,
+ .row.m6 > .span.m5 {
+ width: 83.3333333333%; }
+
+ ._fm7-m1,
+ .row.m7 > .span.m1 {
+ width: 14.2857142857%; }
+
+ ._fm7-m2,
+ .row.m7 > .span.m2 {
+ width: 28.5714285714%; }
+
+ ._fm7-m3,
+ .row.m7 > .span.m3 {
+ width: 42.8571428571%; }
+
+ ._fm7-m4,
+ .row.m7 > .span.m4 {
+ width: 57.1428571429%; }
+
+ ._fm7-m5,
+ .row.m7 > .span.m5 {
+ width: 71.4285714286%; }
+
+ ._fm7-m6,
+ .row.m7 > .span.m6 {
+ width: 85.7142857143%; }
+
+ ._fm8-m1,
+ .row.m8 > .span.m1 {
+ width: 12.5%; }
+
+ ._fm8-m3,
+ .row.m8 > .span.m3 {
+ width: 37.5%; }
+
+ ._fm8-m5,
+ .row.m8 > .span.m5 {
+ width: 62.5%; }
+
+ ._fm8-m7,
+ .row.m8 > .span.m7 {
+ width: 87.5%; }
+
+ ._fm9-m1,
+ .row.m9 > .span.m1 {
+ width: 11.1111111111%; }
+
+ ._fm9-m2,
+ .row.m9 > .span.m2 {
+ width: 22.2222222222%; }
+
+ ._fm9-m4,
+ .row.m9 > .span.m4 {
+ width: 44.4444444444%; }
+
+ ._fm9-m5,
+ .row.m9 > .span.m5 {
+ width: 55.5555555556%; }
+
+ ._fm9-m7,
+ .row.m9 > .span.m7 {
+ width: 77.7777777778%; }
+
+ ._fm9-m8,
+ .row.m9 > .span.m8 {
+ width: 88.8888888889%; }
+
+ ._fm10-m1,
+ .row.m10 > .span.m1 {
+ width: 10%; }
+
+ ._fm10-m3,
+ .row.m10 > .span.m3 {
+ width: 30%; }
+
+ ._fm10-m7,
+ .row.m10 > .span.m7 {
+ width: 70%; }
+
+ ._fm10-m9,
+ .row.m10 > .span.m9 {
+ width: 90%; } }
+@media all and (min-width: 960px) {
+ .mobile-only {
+ display: none; }
+
+ .tablet-only {
+ display: none; }
+
+ .not-desktop {
+ display: none; }
+
+ /*
+ This are the functions (mixins) used to generate the basic scaffolding for our
+ website. Due to the inverted functionality of the grid we rewrote big parts to
+ make them more usable.
+ */
+ /*!
+ Created on : Oct 26, 2013, 7:18:16 PM
+ Author : cesar
+ */
+ div.row {
+ width: 100%;
+ max-width: 960px; }
+
+ ._fl1-l1, .row.l2 > .span.l2, .row.l3 > .span.l3, .row.l4 > .span.l4, .row.l5 > .span.l5, .row.l6 > .span.l6, .row.l7 > .span.l7, .row.l8 > .span.l8, .row.l9 > .span.l9, .row.l10 > .span.l10,
+ .row.l1 > .span.l1 {
+ width: 100%; }
+
+ ._fl2-l1, .row.l4 > .span.l2, .row.l6 > .span.l3, .row.l8 > .span.l4, .row.l10 > .span.l5,
+ .row.l2 > .span.l1 {
+ width: 50%; }
+
+ ._fl3-l1, .row.l6 > .span.l2, .row.l9 > .span.l3,
+ .row.l3 > .span.l1 {
+ width: 33.3333333333%; }
+
+ ._fl3-l2, .row.l6 > .span.l4, .row.l9 > .span.l6,
+ .row.l3 > .span.l2 {
+ width: 66.6666666667%; }
+
+ ._fl4-l1, .row.l8 > .span.l2,
+ .row.l4 > .span.l1 {
+ width: 25%; }
+
+ ._fl4-l3, .row.l8 > .span.l6,
+ .row.l4 > .span.l3 {
+ width: 75%; }
+
+ ._fl5-l1, .row.l10 > .span.l2,
+ .row.l5 > .span.l1 {
+ width: 20%; }
+
+ ._fl5-l2, .row.l10 > .span.l4,
+ .row.l5 > .span.l2 {
+ width: 40%; }
+
+ ._fl5-l3, .row.l10 > .span.l6,
+ .row.l5 > .span.l3 {
+ width: 60%; }
+
+ ._fl5-l4, .row.l10 > .span.l8,
+ .row.l5 > .span.l4 {
+ width: 80%; }
+
+ ._fl6-l1,
+ .row.l6 > .span.l1 {
+ width: 16.6666666667%; }
+
+ ._fl6-l5,
+ .row.l6 > .span.l5 {
+ width: 83.3333333333%; }
+
+ ._fl7-l1,
+ .row.l7 > .span.l1 {
+ width: 14.2857142857%; }
+
+ ._fl7-l2,
+ .row.l7 > .span.l2 {
+ width: 28.5714285714%; }
+
+ ._fl7-l3,
+ .row.l7 > .span.l3 {
+ width: 42.8571428571%; }
+
+ ._fl7-l4,
+ .row.l7 > .span.l4 {
+ width: 57.1428571429%; }
+
+ ._fl7-l5,
+ .row.l7 > .span.l5 {
+ width: 71.4285714286%; }
+
+ ._fl7-l6,
+ .row.l7 > .span.l6 {
+ width: 85.7142857143%; }
+
+ ._fl8-l1,
+ .row.l8 > .span.l1 {
+ width: 12.5%; }
+
+ ._fl8-l3,
+ .row.l8 > .span.l3 {
+ width: 37.5%; }
+
+ ._fl8-l5,
+ .row.l8 > .span.l5 {
+ width: 62.5%; }
+
+ ._fl8-l7,
+ .row.l8 > .span.l7 {
+ width: 87.5%; }
+
+ ._fl9-l1,
+ .row.l9 > .span.l1 {
+ width: 11.1111111111%; }
+
+ ._fl9-l2,
+ .row.l9 > .span.l2 {
+ width: 22.2222222222%; }
+
+ ._fl9-l4,
+ .row.l9 > .span.l4 {
+ width: 44.4444444444%; }
+
+ ._fl9-l5,
+ .row.l9 > .span.l5 {
+ width: 55.5555555556%; }
+
+ ._fl9-l7,
+ .row.l9 > .span.l7 {
+ width: 77.7777777778%; }
+
+ ._fl9-l8,
+ .row.l9 > .span.l8 {
+ width: 88.8888888889%; }
+
+ ._fl10-l1,
+ .row.l10 > .span.l1 {
+ width: 10%; }
+
+ ._fl10-l3,
+ .row.l10 > .span.l3 {
+ width: 30%; }
+
+ ._fl10-l7,
+ .row.l10 > .span.l7 {
+ width: 70%; }
+
+ ._fl10-l9,
+ .row.l10 > .span.l9 {
+ width: 90%; } }
+@media all and (max-width: 480px) {
+ .desktop-only {
+ display: none !important; }
+
+ .tablet-only {
+ display: none; }
+
+ .not-mobile {
+ display: none; } }
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : May 14, 2019, 11:15:57 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Aug 30, 2019, 4:28:26 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.toggle-button, .dial-toggle {
+ display: inline-block;
+ position: relative;
+ vertical-align: middle;
+ cursor: pointer;
+ width: 26px;
+ height: 32px;
+ padding: 0px;
+ background-image: linear-gradient(180deg, #FFF 4px, transparent 4px, transparent 8px, #FFF 8px, #FFF 12px, transparent 12px, transparent 16px, #FFF 16px);
+ background-size: 25px 20px;
+ background-position: center center;
+ background-repeat: no-repeat; }
+ .toggle-button.hidden, .hidden.dial-toggle {
+ display: none; }
+ .toggle-button.dark, .dark.dial-toggle {
+ background-image: linear-gradient(180deg, #777 4px, transparent 4px, transparent 8px, #777 8px, #777 12px, transparent 12px, transparent 16px, #777 16px); }
+ .toggle-button.dark:after, .dark.dial-toggle:after, .toggle-button.dark:before, .dark.dial-toggle:before {
+ background: #242424; }
+ .toggle-button.narrow, .narrow.dial-toggle {
+ background-size: 3px 17px;
+ width: 20px; }
+
+body {
+ overflow-x: hidden; }
+
+* {
+ box-sizing: border-box;
+ -moz-box-sizing: border-box; }
+
+.sidebar {
+ overflow: hidden;
+ position: fixed;
+ display: block;
+ height: 100%;
+ left: 0px;
+ top: 0;
+ width: 300px;
+ max-width: 90%;
+ transform: translate(-300px, 0);
+ background: #FFF;
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
+ border-right: 1px solid #DDD; }
+ .sidebar .menu-title {
+ display: block;
+ color: #999;
+ font-size: 1rem;
+ padding: .8rem 1rem .5rem; }
+ .sidebar .menu-entry {
+ font-size: .8rem;
+ color: #666;
+ display: block; }
+ .sidebar .menu-entry:hover {
+ color: #242424;
+ background: #F7F7F7; }
+ .sidebar .menu-entry.active, .sidebar .menu-entry:active {
+ background-color: #2f97e0;
+ color: #FFF;
+ font-weight: bold; }
+ .sidebar .menu-entry a {
+ padding: .7rem 1rem;
+ display: block;
+ width: 100%; }
+ .sidebar .menu-entry img {
+ vertical-align: middle;
+ height: 1.2em;
+ margin-right: .5rem; }
+ .sidebar .indented {
+ padding-left: 10px;
+ border-left: solid 1px #DDD; }
+ .sidebar .navbar {
+ box-shadow: none; }
+ .sidebar a {
+ color: inherit;
+ text-decoration: none; }
+ .sidebar a:hover {
+ color: #333; }
+ .sidebar a:active {
+ color: #FFF; }
+
+.sidebar:hover {
+ overflow: auto; }
+
+.contains-sidebar {
+ display: none;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.1);
+ z-index: 30; }
+
+/*
+The MIT License
+
+Copyright 2020 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Feb 28, 2020, 5:45:31 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.button, form.regular input[type="submit"] {
+ background: linear-gradient(90deg, #396afc, #2948ff);
+ border-radius: 4px;
+ border: none;
+ padding: 0.5rem 1.4rem;
+ color: #FFF;
+ font-weight: bolder;
+ box-shadow: 2px 1px 3px rgba(0, 0, 0, 0.3);
+ text-decoration: none;
+ vertical-align: middle; }
+ .button.success, form.regular input.success[type="submit"] {
+ background: linear-gradient(-90deg, #2FAD30, #35C537); }
+ .button.borderless, form.regular input.borderless[type="submit"] {
+ background: none;
+ color: #652CA5;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline, form.regular input.outline[type="submit"] {
+ background: none;
+ color: #652CA5;
+ border: solid 1px #652CA5;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.fill-on-hover:hover, form.regular input.outline.fill-on-hover[type="submit"]:hover {
+ background: #652CA5;
+ color: #FFF;
+ border: solid 1px #652CA5; }
+ .button.outline.button-color-grey-100, form.regular input.outline.button-color-grey-100[type="submit"] {
+ background: none;
+ color: #23282C;
+ border: solid 1px #23282C;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-100.fill-on-hover:hover, form.regular input.outline.button-color-grey-100.fill-on-hover[type="submit"]:hover {
+ background: #23282C;
+ color: #FFF;
+ border: solid 1px #23282C; }
+ .button.outline.button-color-grey-200, form.regular input.outline.button-color-grey-200[type="submit"] {
+ background: none;
+ color: #31383D;
+ border: solid 1px #31383D;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-200.fill-on-hover:hover, form.regular input.outline.button-color-grey-200.fill-on-hover[type="submit"]:hover {
+ background: #31383D;
+ color: #FFF;
+ border: solid 1px #31383D; }
+ .button.outline.button-color-grey-300, form.regular input.outline.button-color-grey-300[type="submit"] {
+ background: none;
+ color: #464F56;
+ border: solid 1px #464F56;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-300.fill-on-hover:hover, form.regular input.outline.button-color-grey-300.fill-on-hover[type="submit"]:hover {
+ background: #464F56;
+ color: #FFF;
+ border: solid 1px #464F56; }
+ .button.outline.button-color-grey-400, form.regular input.outline.button-color-grey-400[type="submit"] {
+ background: none;
+ color: #5F6C75;
+ border: solid 1px #5F6C75;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-400.fill-on-hover:hover, form.regular input.outline.button-color-grey-400.fill-on-hover[type="submit"]:hover {
+ background: #5F6C75;
+ color: #FFF;
+ border: solid 1px #5F6C75; }
+ .button.outline.button-color-grey-500, form.regular input.outline.button-color-grey-500[type="submit"] {
+ background: none;
+ color: #74838E;
+ border: solid 1px #74838E;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-500.fill-on-hover:hover, form.regular input.outline.button-color-grey-500.fill-on-hover[type="submit"]:hover {
+ background: #74838E;
+ color: #FFF;
+ border: solid 1px #74838E; }
+ .button.outline.button-color-grey-600, form.regular input.outline.button-color-grey-600[type="submit"] {
+ background: none;
+ color: #8D99A3;
+ border: solid 1px #8D99A3;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-600.fill-on-hover:hover, form.regular input.outline.button-color-grey-600.fill-on-hover[type="submit"]:hover {
+ background: #8D99A3;
+ color: #FFF;
+ border: solid 1px #8D99A3; }
+ .button.outline.button-color-grey-700, form.regular input.outline.button-color-grey-700[type="submit"] {
+ background: none;
+ color: #A9B3B9;
+ border: solid 1px #A9B3B9;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-700.fill-on-hover:hover, form.regular input.outline.button-color-grey-700.fill-on-hover[type="submit"]:hover {
+ background: #A9B3B9;
+ color: #FFF;
+ border: solid 1px #A9B3B9; }
+ .button.outline.button-color-grey-800, form.regular input.outline.button-color-grey-800[type="submit"] {
+ background: none;
+ color: #C1C8CD;
+ border: solid 1px #C1C8CD;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-800.fill-on-hover:hover, form.regular input.outline.button-color-grey-800.fill-on-hover[type="submit"]:hover {
+ background: #C1C8CD;
+ color: #FFF;
+ border: solid 1px #C1C8CD; }
+ .button.outline.button-color-grey-900, form.regular input.outline.button-color-grey-900[type="submit"] {
+ background: none;
+ color: #E6E8EA;
+ border: solid 1px #E6E8EA;
+ font-weight: bold;
+ box-shadow: none; }
+ .button.outline.button-color-grey-900.fill-on-hover:hover, form.regular input.outline.button-color-grey-900.fill-on-hover[type="submit"]:hover {
+ background: #E6E8EA;
+ color: #FFF;
+ border: solid 1px #E6E8EA; }
+ .button.small, form.regular input.small[type="submit"] {
+ font-size: .82rem;
+ padding: .3rem .7rem;
+ border-radius: .18rem;
+ vertical-align: .15rem; }
+
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Jun 28, 2019, 11:48:02 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.dialog {
+ padding: 2.5rem .5rem 2.5rem .5rem;
+ background: #FFF;
+ border-radius: .3rem;
+ border: solid 1px #999;
+ max-width: 90%;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
+ max-height: calc(100% - 9rem);
+ display: inline-block;
+ position: relative; }
+ .dialog .inner {
+ overflow: auto;
+ position: relative;
+ height: 100%; }
+ .dialog .close {
+ color: #AAA;
+ font-weight: bold;
+ text-align: right;
+ cursor: pointer;
+ position: absolute;
+ top: .2rem;
+ right: .5rem;
+ font-size: 1.8rem;
+ line-height: 1.8rem; }
+ .dialog .close:hover {
+ color: #777; }
+ .dialog.transparent {
+ background: transparent;
+ border: none;
+ margin: .5rem auto;
+ max-width: 90%;
+ box-shadow: none; }
+ .dialog.transparent .close {
+ color: #FFF;
+ text-shadow: 0 0 3px #555; }
+
+.dialog-backdrop {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.2);
+ z-index: 9;
+ text-align: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center; }
+
+body.has-dialog {
+ height: 100%;
+ overflow: hidden; }
+
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Jun 28, 2019, 11:48:02 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.gallery {
+ border-radius: .3rem;
+ border: solid 1px #999;
+ width: 100%;
+ height: 100%;
+ background: transparent;
+ border: none;
+ box-shadow: none;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center; }
+ .gallery .close {
+ font-weight: bold;
+ text-align: right;
+ cursor: pointer;
+ position: absolute;
+ top: 1rem;
+ right: 1rem;
+ font-size: 1.8rem;
+ line-height: 1.8rem;
+ color: #FFF;
+ text-shadow: 0 0 3px #555; }
+ .gallery .close:hover {
+ color: #777; }
+ .gallery .inner {
+ max-height: 90%;
+ max-width: 90%; }
+
+.gallery-backdrop {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.8);
+ z-index: 9; }
+
+.navbar {
+ width: 100%;
+ white-space: nowrap;
+ overflow: visible;
+ padding: 0 .4rem;
+ z-index: 5; }
+ .navbar .left,
+ .navbar .right,
+ .navbar .center {
+ padding: 20px 0; }
+ .navbar .right {
+ float: right;
+ text-align: right; }
+ .navbar .left {
+ float: left;
+ text-align: left; }
+ .navbar .center {
+ text-align: center;
+ white-space: nowrap; }
+ .navbar a {
+ text-decoration: none;
+ color: #444;
+ font-weight: bold;
+ display: inline-block;
+ padding: 0 13.3333333333px; }
+ .navbar .logo {
+ display: inline-block;
+ float: left;
+ border: none; }
+ .navbar .logo > * {
+ vertical-align: middle; }
+ .navbar .logo img {
+ height: 10px;
+ width: auto;
+ margin-right: 5px; }
+ .navbar:after {
+ clear: both;
+ content: '';
+ display: table; }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : May 22, 2019, 9:47:20 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.navigation .navigation-item {
+ display: inline-block;
+ padding: .8em 1em;
+ font-size: 1em; }
+.navigation.tabs {
+ border-bottom: solid 1px #DDD; }
+ .navigation.tabs .navigation-item {
+ border: solid 1px transparent;
+ margin-bottom: -1px; }
+ .navigation.tabs .navigation-item.active {
+ font-weight: bold;
+ border-radius: 5px 5px 0 0;
+ border: solid 1px #DDD;
+ border-bottom: solid 1px #FFF; }
+.navigation.pills .navigation-item.active {
+ border-radius: 5px;
+ background-color: #2f97e0;
+ color: #FFF; }
+.navigation.vertical .navigation-item {
+ display: block;
+ width: 100%; }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Nov 4, 2019, 11:43:38 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+/*
+ * Messages are used to present information to the user. This way the application
+ * can show success, error, information and warning messages.
+ */
+.message {
+ border: solid 1px #CCC;
+ border-radius: 3px;
+ background: #FAFAFA;
+ padding: 1rem 2.5rem 1rem 1.5rem;
+ color: #444;
+ position: relative; }
+ .message.error {
+ border-color: #732c2c;
+ color: #632626;
+ background-color: #f09797; }
+ .message.warn {
+ border-color: #2f3014;
+ color: #2f3014;
+ background-color: #e3e87d; }
+ .message.success {
+ border-color: #266326;
+ color: #266326;
+ background-color: #c4f097; }
+ .message.info {
+ border-color: #264463;
+ color: #264463;
+ background-color: #97c4f0; }
+ .message .discard-message {
+ position: absolute;
+ display: block;
+ font-weight: bold;
+ opacity: .6;
+ top: 0;
+ right: 0;
+ padding: 0 .6rem 1rem .6rem;
+ font-size: 1.4rem;
+ cursor: pointer; }
+ .message .discard-message:hover {
+ opacity: 1; }
+ .message .discard-message:before {
+ content: '\00d7'; }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 17, 2019, 11:49:32 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 17, 2019, 11:56:04 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+label {
+ display: inline-block; }
+
+input, textarea {
+ line-height: inherit;
+ margin: 0; }
+
+textarea {
+ resize: vertical; }
+
+input[type="text"],
+textarea {
+ border-radius: 3px;
+ border: solid 1px #CCC;
+ box-shadow: 0 0 0 transparent;
+ transition: box-shadow .15s ease; }
+ input[type="text"]:focus,
+ textarea:focus {
+ border-color: #279af1;
+ box-shadow: 0px 0px 2px #279af1;
+ outline: none; }
+
+select {
+ border-radius: 3px;
+ border: solid 1px #CCC;
+ box-shadow: 0 0 0 transparent;
+ transition: box-shadow .15s ease;
+ background: #FFF; }
+ select:focus {
+ border-color: #279af1;
+ box-shadow: 0px 0px 2px #279af1;
+ outline: none; }
+
+fieldset {
+ border: none;
+ padding: 0;
+ margin: 0; }
+
+legend {
+ font-size: 1.3rem;
+ margin-bottom: .3rem; }
+
+input[type="submit"]:not(.disabled), button:not(.disabled) {
+ cursor: pointer; }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 17, 2019, 11:59:07 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.frm-ctrl {
+ display: block;
+ width: 100%; }
+ .frm-ctrl.right {
+ text-align: right; }
+
+.frm-group {
+ margin-bottom: 1rem; }
+
+.frm-inline {
+ display: flex;
+ flex-flow: row wrap; }
+ .frm-inline .frm-ctrl {
+ display: inline-block;
+ width: auto; }
+
+.frm-lbl {
+ padding: .75rem .4rem;
+ color: #444;
+ font-size: .9rem; }
+
+input[type="text"].frm-ctrl,
+textarea.frm-ctrl {
+ padding: .75rem .5rem; }
+
+/*
+ * Checkbox specific styling
+ */
+input[type="checkbox"].frm-ctrl {
+ display: none; }
+
+span.frm-ctrl-chk {
+ display: inline-block;
+ width: 1.3rem;
+ height: 1.3rem;
+ border-radius: .25rem;
+ border: solid 1px #CCC;
+ background-color: #DDD;
+ position: relative;
+ margin-right: .2rem;
+ vertical-align: -.4rem;
+ transition: background-color .3s ease; }
+ span.frm-ctrl-chk:before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 1.3rem;
+ width: 1.3rem;
+ background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D%228%22%20viewBox%3D%220%200%208%208%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M6.41%200l-.69.72-2.78%202.78-.81-.78-.72-.72-1.41%201.41.72.72%201.5%201.5.69.72.72-.72%203.5-3.5.72-.72-1.44-1.41z%22%2F%3E%3C%2Fsvg%3E%0A");
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: 0 0;
+ border-radius: 50%;
+ transition: background-size .15s ease; }
+
+span.frm-ctrl-chk.toggle {
+ display: inline-block;
+ width: 2rem;
+ height: 1.3rem;
+ border-radius: .65rem;
+ background-color: #CCC;
+ position: relative;
+ margin-right: .2rem;
+ vertical-align: -.4rem;
+ transition: background-color .3s ease;
+ border: none; }
+ span.frm-ctrl-chk.toggle:before {
+ content: '';
+ position: absolute;
+ top: .15rem;
+ left: .15rem;
+ height: 1rem;
+ width: 1rem;
+ background-color: #FFF;
+ border-radius: 50%;
+ transition: left .3s ease; }
+
+input[type="checkbox"].frm-ctrl:checked + span.frm-ctrl-chk {
+ background-color: #56a1d6;
+ border: solid 1px #56a1d6; }
+ input[type="checkbox"].frm-ctrl:checked + span.frm-ctrl-chk:before {
+ background-size: .8rem .8rem; }
+ input[type="checkbox"].frm-ctrl:checked + span.frm-ctrl-chk.toggle {
+ border: none; }
+ input[type="checkbox"].frm-ctrl:checked + span.frm-ctrl-chk.toggle:before {
+ left: .9rem; }
+
+/*
+ * Radio specific styling
+ */
+input[type="radio"].frm-ctrl {
+ display: none; }
+
+span.frm-ctrl-rad {
+ display: inline-block;
+ border: solid .05rem #777;
+ width: 1.3rem;
+ height: 1.3rem;
+ border-radius: .65rem;
+ background-color: #DDD;
+ position: relative;
+ margin-right: .2rem;
+ vertical-align: -.4rem;
+ transition: background-color .3s ease; }
+ span.frm-ctrl-rad:before {
+ position: absolute;
+ background: #FFF;
+ top: .65rem;
+ left: .65rem;
+ height: .0rem;
+ width: .0rem;
+ content: '';
+ border-radius: 50%;
+ transition: left .3s ease, top .3s ease, width .3s ease, height .3s ease, opacity .3s ease; }
+
+input[type="radio"].frm-ctrl:checked + span.frm-ctrl-rad {
+ background-color: #56a1d6; }
+ input[type="radio"].frm-ctrl:checked + span.frm-ctrl-rad:before {
+ top: .3rem;
+ left: .3rem;
+ height: .6rem;
+ width: .6rem;
+ background-color: #FFF;
+ color: #FFF;
+ line-height: .9rem;
+ font-size: .9rem;
+ text-align: center;
+ font-weight: bold; }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Aug 22, 2019, 4:19:27 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+select.frm-ctrl {
+ padding: .75rem .4rem;
+ background-repeat: no-repeat;
+ background-position: center right 1.1rem;
+ background-size: .8rem .8rem;
+ padding-right: 2.4rem;
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ appearance: none;
+ background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E"); }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Aug 22, 2019, 4:33:17 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.frm-ctrl-grp {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+ transition: box-shadow .2s ease; }
+ .frm-ctrl-grp .frm-ctrl {
+ width: 1px;
+ flex-grow: 1;
+ flex-shrink: 1;
+ border-radius: 0;
+ border-left-style: none;
+ border-right-style: none; }
+ .frm-ctrl-grp .frm-ctrl:first-child {
+ border-radius: 3px 0 0 3px;
+ border-left-style: solid; }
+ .frm-ctrl-grp .frm-ctrl:last-child {
+ border-radius: 0 3px 3px 0;
+ border-right-style: solid; }
+ .frm-ctrl-grp .frm-ctrl.fixed-width {
+ flex-grow: 0;
+ flex-shrink: 0; }
+ .frm-ctrl-grp .frm-ctrl.narrow {
+ width: 7rem; }
+ .frm-ctrl-grp .frm-ctrl.medium {
+ width: 12rem; }
+ .frm-ctrl-grp .frm-ctrl:focus {
+ box-shadow: none;
+ border-color: #CCC; }
+ .frm-ctrl-grp:focus-within {
+ box-shadow: 0px 0px 2px #279af1; }
+ .frm-ctrl-grp:focus-within .frm-ctrl {
+ border-color: #279af1; }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Classes in this file manage the flow of the content, they provide utility classes
+ like right, left and center for test alignment, etc
+
+ Created on : Nov 20, 2019, 12:03:46 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.align-left {
+ text-align: left; }
+
+.align-right {
+ text-align: right; }
+
+.align-center {
+ text-align: center; }
+
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Nov 20, 2019, 11:58:35 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.spacer.minuscule {
+ height: .3rem; }
+.spacer.smaller {
+ height: .7rem; }
+.spacer.small {
+ height: 1rem; }
+.spacer.medium {
+ height: 2rem; }
+.spacer.large {
+ height: 3rem; }
+.spacer.huge {
+ height: 4rem; }
+
+.horizontal-spacer {
+ display: inline-block;
+ height: 1px;
+ vertical-align: middle; }
+ .horizontal-spacer.minuscule {
+ width: .3rem; }
+ .horizontal-spacer.smaller {
+ width: .7rem; }
+ .horizontal-spacer.small {
+ width: 1rem; }
+ .horizontal-spacer.medium {
+ width: 2rem; }
+ .horizontal-spacer.large {
+ width: 3rem; }
+ .horizontal-spacer.huge {
+ width: 4rem; }
+
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Oct 10, 2017, 11:59:43 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : 21.03.2018, 15:18:50
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.has-dropdown {
+ position: relative; }
+
+.dropdown {
+ display: none;
+ position: absolute;
+ top: 100%;
+ left: -20px;
+ width: 100%;
+ min-width: 300px;
+ max-width: 100%;
+ margin-top: 20px;
+ background: #FFF;
+ border: solid 1px #DDD;
+ border-radius: 3px;
+ padding: 5px;
+ z-index: 99999999999;
+ padding: 10px;
+ box-shadow: 0 0 7px rgba(0, 0, 0, 0.2); }
+ .dropdown:before, .dropdown:after {
+ content: '';
+ height: 10px;
+ width: 10px;
+ display: block;
+ position: absolute;
+ bottom: 100%; }
+ .dropdown:before {
+ left: 20px;
+ background-image: linear-gradient(-225deg, transparent 7px, #DDD 7px, #DDD 8px, #FFF 9px); }
+ .dropdown:after {
+ left: 30px;
+ background-image: linear-gradient(225deg, transparent 7px, #DDD 7px, #DDD 8px, #FFF 9px); }
+ .dropdown.right-bound {
+ right: -20px;
+ left: auto; }
+ .dropdown.right-bound:before {
+ left: auto;
+ right: 30px; }
+ .dropdown.right-bound:after {
+ left: auto;
+ right: 20px; }
+ .dropdown.unpadded {
+ padding: 0; }
+ .dropdown .padded {
+ padding: 5px; }
+
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Oct 10, 2017, 11:59:49 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Oct 10, 2017, 11:58:05 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+input[type=checkbox].styled {
+ display: none; }
+ input[type=checkbox].styled + span.toggle {
+ display: inline-block;
+ position: relative;
+ width: 1.5em;
+ height: .5em;
+ background-color: #DDD;
+ border-radius: 5px;
+ vertical-align: .11em;
+ margin: 0 .4em;
+ transition: background-color .3s linear; }
+ input[type=checkbox].styled + span.toggle:before {
+ display: block;
+ position: absolute;
+ top: -.20em;
+ left: 0;
+ height: .85em;
+ width: .9em;
+ border-radius: 50%;
+ background: #FFF;
+ border: solid 1px #777;
+ content: '';
+ transition: left .3s ease; }
+ input[type=checkbox].styled:checked + span.toggle {
+ background-color: #a1d49d; }
+ input[type=checkbox].styled:checked + span.toggle:before {
+ left: 50%; }
+
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 6, 2018, 5:21:03 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+form.condensed {
+ margin: 0 auto;
+ /*
+ * Textareas do have specific styles, including smaller text to make them more
+ * useful for users typing in bigger segments of text
+ */ }
+ form.condensed .field {
+ margin: 0; }
+ form.condensed label {
+ display: none; }
+ form.condensed input,
+ form.condensed textarea {
+ /*
+ * These remove the annoyng styles from the iOS layout that will style
+ * input for you.
+ */
+ -webkit-appearance: none;
+ -moz-appearance: none; }
+ form.condensed input[type="email"],
+ form.condensed input[type="password"],
+ form.condensed input[type="text"],
+ form.condensed textarea {
+ border: none;
+ border-top: none;
+ border-bottom: none;
+ border-radius: 0;
+ margin: 0;
+ font-size: 17px;
+ width: 100%;
+ padding: 10px;
+ box-sizing: border-box;
+ /*Make the splitter lines. We don't use border to avoid them invading the border */
+ background-image: linear-gradient(180deg, #DDD 1px, #FFF 1px); }
+ form.condensed textarea {
+ font-size: .9em;
+ height: 8em; }
+ form.condensed .field:first-child input[type="email"],
+ form.condensed .field:first-child input[type="text"],
+ form.condensed .field:first-child input[type="password"],
+ form.condensed .field:first-child textarea {
+ border-top: solid 1px #999;
+ background-image: linear-gradient(180deg, #ccc 0%, #fff 8%); }
+ form.condensed input[type="submit"] {
+ border: solid 1px #529EBB;
+ border-top: none;
+ font-family: sans-serif;
+ background-color: #25A9F8;
+ color: #FFF;
+ margin: 0;
+ font-size: 20px;
+ width: 100%;
+ padding: 10px;
+ cursor: pointer;
+ box-sizing: border-box;
+ background-image: linear-gradient(0deg, #0571B1 0%, #25A9F8 6%); }
+ form.condensed input[type="submit"]:disabled {
+ color: #b3b3b3;
+ background: #045280 !important;
+ cursor: not-allowed; }
+ form.condensed .message {
+ position: relative;
+ padding: 10px 10px;
+ font-size: 13px;
+ border-width: 0 1px;
+ border-style: solid; }
+ form.condensed .message.success {
+ border-color: #3C7619;
+ background: #84D950;
+ color: #3C7619; }
+ form.condensed .message.success:after {
+ border-color: transparent transparent #84D950 transparent; }
+ form.condensed .message.info {
+ border-color: #CCC;
+ background: #EEE;
+ color: #555; }
+ form.condensed .message.info:after {
+ border-color: transparent transparent #EEE transparent; }
+ form.condensed .message.error {
+ border-color: #590C0E;
+ background: #F2B5B7;
+ color: #490C0E; }
+ form.condensed .message.error:after {
+ border-color: transparent transparent #F2B5B7 transparent; }
+ form.condensed .message:after {
+ position: absolute;
+ bottom: 100%;
+ right: 20px;
+ display: block;
+ width: 0;
+ height: 0;
+ content: '';
+ border-style: none solid solid solid;
+ border-color: transparent transparent #CCC transparent;
+ border-width: 7px; }
+ form.condensed .description {
+ background: #FFF;
+ padding: 10px;
+ color: #333;
+ font-size: 13px; }
+ form.condensed.standalone {
+ max-width: 350px;
+ border-radius: 4px;
+ overflow: hidden;
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.7); }
+ form.condensed.standalone input:first-child,
+ form.condensed.standalone input:last-child {
+ background-image: none;
+ border-top: none; }
+ form.condensed.standalone input[type="submit"] {
+ transition: background-color .5s ease, background-size .5s ease;
+ background-size: 0 0;
+ background-repeat: no-repeat;
+ background-position: 50% 50%; }
+ form.condensed.standalone input[type="submit"]:hover {
+ background-color: #1599E8; }
+ form.condensed.standalone input[type="submit"]:active {
+ background-color: #35B9F8; }
+ form.condensed.standalone .message {
+ border-left: none;
+ border-right: none; }
+
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 7, 2018, 2:39:55 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 7, 2018, 2:39:33 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.toggle-button, .dial-toggle {
+ display: inline-block;
+ position: relative;
+ vertical-align: middle;
+ width: 38px;
+ height: 17px;
+ padding: 0px;
+ background-image: linear-gradient(180deg, #FFF 3px, transparent 3px, transparent 7px, #FFF 7px, #FFF 10px, transparent 10px, transparent 14px, #FFF 14px);
+ background-size: 20px 17px;
+ background-position: center center;
+ background-repeat: no-repeat; }
+ .toggle-button.hidden, .hidden.dial-toggle {
+ display: none; }
+ .toggle-button.medium, .medium.dial-toggle {
+ background-image: linear-gradient(180deg, #777 3px, transparent 3px, transparent 7px, #777 7px, #777 10px, transparent 10px, transparent 14px, #777 14px); }
+ .toggle-button.medium:after, .medium.dial-toggle:after, .toggle-button.medium:before, .medium.dial-toggle:before {
+ background: #242424; }
+ .toggle-button.dark, .dark.dial-toggle {
+ background-image: linear-gradient(180deg, #242424 3px, transparent 3px, transparent 7px, #242424 7px, #242424 10px, transparent 10px, transparent 14px, #242424 14px); }
+ .toggle-button.dark:after, .dark.dial-toggle:after, .toggle-button.dark:before, .dark.dial-toggle:before {
+ background: #242424; }
+ .toggle-button.narrow, .narrow.dial-toggle {
+ background-size: 3px 17px;
+ width: 20px; }
+
+._navbar {
+ background: #EEE;
+ box-shadow: 0 2px 2px #DDD;
+ border-bottom: 1px solid #CCC;
+ display: table;
+ width: 100%;
+ z-index: 5; }
+ ._navbar .left,
+ ._navbar .right {
+ display: table-cell;
+ padding: 15px 10px; }
+ ._navbar .right {
+ text-align: right; }
+ ._navbar a {
+ text-decoration: none;
+ color: #444;
+ font-weight: bold;
+ display: inline-block;
+ padding: 0 10px; }
+ ._navbar .logo {
+ display: inline-block;
+ float: left;
+ border: none; }
+ ._navbar .logo > * {
+ vertical-align: middle; }
+ ._navbar .logo img {
+ height: 20px;
+ margin-right: 5px; }
+
+.admin-navigation {
+ background: #222;
+ color: #FFF;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); }
+ .admin-navigation .menu-item {
+ background: #222;
+ color: #FFF;
+ padding: 10px;
+ width: 100%;
+ display: inline-block; }
+ .admin-navigation .menu-item:hover {
+ background: #FFF;
+ color: #222; }
+
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Apr 17, 2016, 1:23:34 AM
+ Author : cesar
+*/
+ul.pagination {
+ list-style: none;
+ text-align: center; }
+ ul.pagination li {
+ display: inline-block;
+ border: solid 1px #86b8e3;
+ border-left: none;
+ padding: 5px 12px; }
+ ul.pagination li:first-child {
+ border-left: solid 1px #86b8e3;
+ border-radius: 3px 0 0 3px; }
+ ul.pagination li:last-child {
+ border-radius: 0 3px 3px 0; }
+ ul.pagination li.disabled, ul.pagination li.disabled a {
+ color: #999; }
+ ul.pagination li.current, ul.pagination li.current a {
+ background: #25A9F8;
+ color: #FFF; }
+
+.separator {
+ border-top: solid 1px #CCC;
+ margin: 10px 0; }
+ .separator.large {
+ margin: 20px 0; }
+ .separator.light {
+ border-top: solid 1px #DDD; }
+
+.editable-property {
+ display: block; }
+ .editable-property > * {
+ vertical-align: top; }
+ .editable-property.mid-aligned > * {
+ vertical-align: middle; }
+ .editable-property .property-name {
+ display: inline-block;
+ width: 33%; }
+ .editable-property .property-value {
+ display: inline-block;
+ width: 50%; }
+ .editable-property .edit-link {
+ display: inline-block;
+ width: 17%; }
+ .editable-property .edit-link .cancel {
+ color: #a00; }
+
+.message {
+ padding: 10px 10px;
+ font-size: 13px;
+ border-color: #777;
+ border-width: 3px;
+ border-style: none none none solid;
+ border-radius: 2px; }
+ .message a {
+ font-weight: bold;
+ color: inherit; }
+ .message.success {
+ border-color: #3C7619;
+ background: #84D950;
+ color: #3C7619; }
+ .message.error {
+ border-color: #8c1013;
+ background: #F2B5B7;
+ color: #490C0E; }
+
+#icon-upload-wrap {
+ position: relative;
+ width: 128px;
+ height: 128px;
+ border: 2px dashed rgba(0, 0, 0, 0.5);
+ border-radius: 10px;
+ background: url("../img/upload.svg") no-repeat center center;
+ background-size: 64px 64px; }
+ #icon-upload-wrap > input[type="file"] {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: inherit;
+ height: inherit;
+ opacity: 0; }
+ #icon-upload-wrap.uploading {
+ background: none; }
+ #icon-upload-wrap.uploading:before {
+ content: '';
+ display: block;
+ width: 48px;
+ height: 48px;
+ margin: 40px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: 50%;
+ border: 6px solid rgba(0, 0, 0, 0.3);
+ border-left-color: black;
+ box-sizing: border-box;
+ animation: spin .6s linear infinite; }
+ #icon-upload-wrap.uploaded {
+ background: no-repeat center center;
+ background-size: cover; }
+
+@keyframes spin {
+ from {
+ transform: rotate(0deg); }
+ to {
+ transform: rotate(360deg); } }
+.dials {
+ border-left: solid 1px #CCC;
+ font-size: .8em; }
+ .dials ul {
+ margin: 2px;
+ padding-left: 10px;
+ list-style-type: none; }
+ .dials a {
+ display: inline-block;
+ padding: 2px;
+ text-decoration: none; }
+ .dials a:hover {
+ background: #EEE; }
+
+.dial-toggle {
+ display: block;
+ width: 23px !important;
+ height: 24px;
+ position: absolute;
+ top: 0;
+ right: 0px;
+ display: none;
+ background-color: #FFF;
+ border-radius: 50%;
+ box-shadow: 0 0 2px #CCC; }
+
+@media all and (max-width: 960px) {
+ .has-dials {
+ position: relative; }
+
+ .dial-toggle {
+ display: block; }
+
+ .dials {
+ border: solid 1px #CCC;
+ padding: 20px 0;
+ background: #FFF;
+ position: fixed;
+ bottom: 30%;
+ left: 5%;
+ margin: 0 auto;
+ width: 90% !important;
+ display: none;
+ box-shadow: 0 0 3px #CCC;
+ z-index: 10;
+ border-radius: 10px; }
+ .dials ul {
+ padding: 0;
+ margin: 0; }
+ .dials a {
+ display: block;
+ padding: 15px 30px;
+ width: 100%;
+ color: #555;
+ font-size: 1.2em;
+ font-weight: bold; }
+
+ .dials-curtain {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ z-index: 9;
+ background: rgba(0, 0, 0, 0.25);
+ transition: .7s opacity 0s ease;
+ opacity: 1; }
+ .dials-curtain.dnd {
+ opacity: 0; } }
+
+/*# sourceMappingURL=app.css.map */
diff --git a/assets/css/app.css.map b/assets/css/app.css.map
new file mode 100644
index 0000000..b9e6afc
--- /dev/null
+++ b/assets/css/app.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "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",
+"sources": ["../scss/app.scss","../scss/_color.scss","../scss/_/_.scss","../scss/_/_reset.scss","../scss/_/scaffolding/_scaffolding.scss","../scss/_/mixins/_grid.scss","../scss/_/scaffolding/_scaffolding_mobile.scss","../scss/_/scaffolding/_scaffolding_tablet.scss","../scss/_/scaffolding/_scaffolding_desktop.scss","../scss/_/ui/_ui.scss","../scss/_/ui/sidebar/_toggle.scss","../scss/_/ui/sidebar/_sidebar.scss","../scss/_/ui/buttons/_button.scss","../scss/_/ui/_dialog.scss","../scss/_/ui/_gallery.scss","../scss/_/ui/_navbar.scss","../scss/_/ui/_navigation.scss","../scss/_/ui/_message.scss","../scss/_/ui/_form.scss","../scss/_/ui/form/_reset.scss","../scss/_/ui/form/_controls.scss","../scss/_/ui/form/_select.scss","../scss/_/ui/form/_groups.scss","../scss/_/ui/_flow.scss","../scss/_/ui/_whitespace.scss","../scss/ui/_ui.scss","../scss/ui/_dropdown.scss","../scss/ui/form/_form.scss","../scss/ui/form/_checkbox.scss","../scss/ui/form/_condensed.scss","../scss/ui/layout/__layout.scss","../scss/ui/layout/_toggle.scss","../scss/_navbar.scss","../scss/_admin.scss","../scss/_pagination.scss","../scss/_properties.scss","../scss/_messages.scss","../scss/_icon-upload.scss","../scss/_dials.scss"],
+"names": [],
+"file": "app.css"
+}
diff --git a/assets/css/drawer.css b/assets/css/drawer.css
new file mode 100644
index 0000000..9dd3115
--- /dev/null
+++ b/assets/css/drawer.css
@@ -0,0 +1,83 @@
+@charset "UTF-8";
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : 21.03.2018, 14:52:40
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+.app-switcher.toggle {
+ vertical-align: middle;
+ background-color: #777;
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ cursor: pointer;
+ background-image: linear-gradient(0deg, transparent 0px, transparent 5px, #EAEAEA 5px, #EAEAEA 7.5px, transparent 7.5px, transparent 12.5px, #EAEAEA 12.5px, #EAEAEA 15px, transparent 15px, transparent 20px), linear-gradient(90deg, transparent 0px, transparent 5px, #EAEAEA 5px, #EAEAEA 7.5px, transparent 7.5px, transparent 12.5px, #EAEAEA 12.5px, #EAEAEA 15px, transparent 15px, transparent 20px); }
+
+.app-drawer {
+ text-align: left; }
+ .app-drawer .app-entry {
+ padding: 10px 12px;
+ border-radius: 2px;
+ border: solid 1px transparent;
+ background-color: transparent;
+ display: inline-block;
+ width: 100%;
+ text-align: center;
+ text-decoration: none;
+ transition: border .1s ease-in, background-color .1s ease-in; }
+ .app-drawer .app-entry:hover {
+ background-color: #F9F9F9;
+ border: solid 1px #CCC; }
+ .app-drawer .app-icon-drawer {
+ margin: 0 auto;
+ width: 90%;
+ height: auto;
+ display: block; }
+ .app-drawer .app-name-drawer {
+ text-align: center;
+ display: block;
+ font-size: .75em;
+ color: #242424;
+ margin-top: .75em;
+ margin-bottom: .25em;
+ width: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-weight: normal; }
+ .app-drawer .footer {
+ background: #EEE;
+ text-align: center;
+ display: block;
+ padding: 10px 15px;
+ color: #888;
+ font-weight: bold;
+ font-size: .8em;
+ background-image: linear-gradient(180deg, #CCC 0px, transparent 3px); }
+ .app-drawer .footer:hover {
+ color: #777;
+ background-color: #D5D5D5; }
+
+/*# sourceMappingURL=drawer.css.map */
diff --git a/assets/css/drawer.css.map b/assets/css/drawer.css.map
new file mode 100644
index 0000000..c25e0ee
--- /dev/null
+++ b/assets/css/drawer.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": ";AAAA;;;;;;;;;;;;;;;;;;;;;;EAsBE;AACF;;;EAGE;AAMF,oBAAqB;EACpB,cAAc,EAAE,MAAM;EACtB,gBAAgB,EANS,IAAI;EAO7B,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAA2B;EAClC,MAAM,EAAE,IAA2B;EACnC,MAAM,EAAE,OAAO;EAEf,gBAAgB,EACf,2XAgBC;;AAKH,WACA;EAEC,UAAU,EAAE,IAAI;EAEhB,sBAAW;IACV,OAAO,EAAE,SAAS;IAClB,aAAa,EAAE,GAAG;IAClB,MAAM,EAAE,qBAAqB;IAC7B,gBAAgB,EAAE,WAAW;IAC7B,OAAO,EAAE,YAAY;IACrB,KAAK,EAAE,IAAI;IACX,UAAU,EAAE,MAAM;IAClB,eAAe,EAAE,IAAI;IAErB,UAAU,EAAE,gDAAgD;IAE5D,4BAAQ;MACP,gBAAgB,EAAE,OAAO;MACzB,MAAM,EAAE,cAAc;EAIxB,4BAAiB;IAChB,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,GAAG;IACV,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,KAAK;EAGf,4BAAiB;IAChB,UAAU,EAAE,MAAM;IAClB,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,KAAK;IAChB,KAAK,EAAE,OAAO;IACd,UAAU,EAAE,KAAK;IACjB,aAAa,EAAE,KAAK;IACpB,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;IACnB,QAAQ,EAAE,MAAM;IAChB,aAAa,EAAE,QAAQ;IACvB,WAAW,EAAE,MAAM;EAGpB,mBAAQ;IACP,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,MAAM;IAClB,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,IAAI;IAEf,gBAAgB,EAAE,kDAAkD;IAEpE,yBAAQ;MACP,KAAK,EAAE,IAAI;MACX,gBAAgB,EAAE,OAAO",
+"sources": ["../scss/ui/_app-switcher.scss"],
+"names": [],
+"file": "drawer.css"
+}
diff --git a/assets/css/kit.css b/assets/css/kit.css
deleted file mode 100644
index 07b181e..0000000
--- a/assets/css/kit.css
+++ /dev/null
@@ -1,481 +0,0 @@
-/*Page Wrappers*/
-html {
- height: 100%;
-}
-
-body {
- display: block;
- height: 100%;
- margin: 0;
- font-family: arial;
- min-width: 960px;
-}
-
-.outerWrapper {
- min-height: 100%;
- margin-bottom: -50px; /*Footer height*/
-}
-
-.innerWrapper {
- margin-bottom: 50px;
- background: #FFF;
-}
-
-/*Page navigation*/
-#pageNavigation {
- display: block;
- width: 100%;
- height: 30px;
- background: #282828;
- color: #FFF; /*Default color for navigation*/
- box-shadow: 0px 2px 3px #777;
- border-bottom: solid 1px #999;
- vertical-align: top;
-}
-
-#pageNavigation #logo, #pageNavigation a {
- display: inline-block;
- height: 20px;
- font-size: 17px;
- padding: 5px 10px;
-}
-
-#pageNavigation #logo {
- float: left;
-}
-
-#pageNavigation #logo:hover, #pageNavigation a:hover {
- background: #CCC;
- color: #282828;
-}
-
-#pageNavigation #userCP {
- float: right;
-}
-
-#pageNavigation form#search {
- display: inline-block;
- position: relative;
- width: 150px;
- height: 15px;
- margin-left: 30px;
-}
-
-#pageNavigation form#search input[type="text"]:focus {
- background: #FFF;
- color: #282828;
- box-shadow: 0px 0px 2px #78C0FF;
- -moz-transition: background-color 1s ease;
-}
-
-#pageNavigation form#search input[type="text"] {
- padding: 2px;
- border: solid 1px #999;
- background: #999;
- overflow: hidden;
- margin: 4px 10px 0 10px;
- border-radius: 4px;
- box-shadow: inset 1px 1px 3px #777;
- background-image: -moz-linear-gradient(to bottom, #BBB, #B7B7B7 50%, #BBB 51%);
- color: #777;
- position: absolute;
- top: 0;
- left: 0;
- width: 135px;
- height: 100%;
-}
-
-#pageNavigation form#search input[type="submit"] {
- background: url('search.png') no-repeat;
- border: none;
- font-size: 0;
- display: block;
- position: absolute;
- top: 7px;
- right: 3px;
- width: 15px;
- height: 15px;
- overflow:hidden;
-}
-
-/*Section navigation*/
-
-#sectionNavigation {
- margin-top: 15px;
- border-bottom: solid 1px #CCC;
- vertical-align: bottom;
- display: block;
- height: 50px;
-}
-
-#sectionNavigation .sectionIcon {
- width: 50px;
- height: 50px;
- margin: 0;
- float: left;
-}
-
-#sectionNavigation h1 {
- display: inline-block;
- margin: 0 20px 0 10px;
- float: left;
-}
-
-#sectionNavigation h1 small {
- display: block;
-}
-
-#sectionNavigation .tab {
- float: left;
- display: inline-block;
- margin-left: 10px;
- height: 24px;
- border-style: solid solid none solid;
- border-color: #CCC #CCC #FFF #CCC;
- border-width: 1px;
- padding: 5px 10px;
- margin-top: 15px;
- border-radius: 4px 4px 0 0;
- color: #44609D;
-}
-
-#sectionNavigation .tab:hover {
- color: #8EB2DB;
-}
-
-#sectionNavigation .tab.active {
- border-style: solid;
- color: #555;
-}
-
-#sectionNavigation .tab.active {
- color: #555;
-}
-
-/*Left Sidebar*/
-#leftSidebar {
- float: left;
- width: 180px;
- margin-left: 10px;
-}
-
-#leftSidebar .group {
- font-size: 13px;
-}
-
-#leftSidebar .group .field {
- display: block;
- color: #AAA;
- margin-top: 10px;
-}
-
-#leftSidebar .group .info {
- display: block;
- color: #2B65E4;
- margin-top: 5px;
- margin-left: 5px;
-}
-
-.fluidContent.withLeftSidebar {
- margin-left: 200px;
-}
-
-/*Contents*/
-.fluidContent {
-
-}
-
-.fixedWrapper {
- background: #F7F7F7;
- box-shadow: 0 10px 10px #F7F7F7;
-}
-
-.fixedContent {
- display: block;
- width: 900px;
- margin: 0px auto 25px;
- border: solid 1px #CCC;
- border-radius: 0 0 3px 3px;
- box-shadow: 0 5px 5px #CCC;
- background: #FFF;
- border-top: none
-}
-
-.fixedContent.padded {
- width: 910px;
- padding: 25px;
-}
-
-@media all and (max-width:1200px) {
- .fixedContent.padded.withLeftSidebar {
- margin-left: 230px ;
- width: 680px;
- }
-}
-
-/*Footer*/
-#footer {
- height: 20px;
- padding: 20px 0 10px 0;
- color: #777;
- font-size: 14px;
- text-align: center;
-}
-
-/*General elements*/
-h1 {
- font-size: 18px;
- color: #282828;
-}
-
-h1 small {
- font-size: 16px;
- color: #757575;
-}
-
-/*Gallery*/
-.polaroid {
- border-radius: 2px 2px 2px 2px;
- display: inline-block;
- height: 185px;
- margin-left: 10px;
- margin-top: 10px;
- width: 170px;
-}
-.polaroid .thumb {
- border: 1px solid #AAAAAA;
- box-shadow: 2px 2px 7px #CCCCCC;
- margin: 0;
- max-height: 150px;
- max-width: 150px;
- padding: 5px;
-}
-.polaroid .polaroidCaption {
- color: #282828;
- display: block;
- font-size: 12px;
- margin-top: 10px;
- text-align: center;
- width: 180px;
-}
-.corrector {
- display: table-cell;
- height: 160px;
- text-align: center;
- vertical-align: middle;
- width: 170px;
-}
-
-/*Forms*/
-
-form.data.narrow{
- max-width: 500px;
-}
-
-form.data.wide{
- max-width: 910px;
-}
-
-form.data label {
- display: inline-block;
- color: #207FC5;
- font-size: 13px;
- vertical-align: top;
-}
-
-form.data.narrow label {
- width: 120px;
-}
-
-form.data input[type="text"]:-moz-placeholder, form.data input[type="email"]:-moz-placeholder, form.data input[type="password"]:-moz-placeholder, form.data textarea:-moz-placeholder {
- color: #90C5ED;
-}
-
-form.data input[type="text"], form.data input[type="email"], form.data input[type="password"], form.data textarea {
- background: #FFF;
- box-shadow: 2px 2px 2px /*#BCDCF4*/ rgba(188, 220, 244, 0.70) inset, .2px .2px 1px #AAA;
- border-radius: 4px;
- padding: 5px;
- border: solid 1px #207FC5;
- color: #207FC5;
- -moz-transition: box-shadow .5s ease, border-color .5s ease, color .5s ease;
-}
-
-form.data.narrow input[type="text"],
-form.data.narrow input[type="email"],
-form.data.narrow input[type="password"],
-form.data.narrow textarea {
- width: 200px;
- min-width: 200px;
- max-width: 200px;
-}
-
-form.data.narrow .footer {
- display: block;
- width: 340px;
- text-align: right;
-}
-
-form.data input[type="submit"] {
- display: inline-block;
- padding: 5px 10px;
- border-radius: 4px;
- color: #FFF;
- border: solid 1px #0A2A41; /*Colorwizard: 207FC5*/
- background-color: #11466D;
- background-image: -moz-linear-gradient(to bottom, #207FC5, #11466D);
- background-size: 100% 100%;
- background-repeat: no-repeat;
- -moz-transition: background-position 0.7s ease;
- cursor: pointer;
-}
-
-form.data input[type="submit"]:hover,
-form.data input[type="submit"]:active ,
-form.data input[type="submit"]:focus {
- background-position: 0 -30px;
-}
-
-form.data input.invalid,
-form.data input[type="text"]:invalid,
-form.data input[type="email"]:invalid,
-form.data input[type="password"]:invalid,
-form.data textarea:invalid {
- border: solid 1px #C99;
- color: #C99;
- box-shadow: 2px 2px 2px /*#FBB*/ rgba(255, 187, 187, 0.7) inset, 0px 0px 5px /*#FCC*/rgba(255, 204, 204, 0.7);
-}
-
-form.data input.formSecondary {
- background: none;
- border: none;
- cursor: pointer;
- color: #844;
-}
-
-form.data input.formSecondary:hover,
-form.data input.formSecondary:focus {
- text-decoration: underline;
-}
-
-/*Tags*/
-.tag {
- display: inline-block;
- border-radius: 3px;
- border-style: solid;
- color: #FFF;
- border-width: 1px;
- padding: 2px 7px;
- font-weight: 500;
- text-shadow: -.0px -.7px .7px #282828;
- margin-right: 4px;
- font-family: sans-serif;
-}
-.tag.green {
- border-color: #2F8A24;
- background: #2F7224;
-}
-.tag.red {
- border-color: #C66;
- background: #933;
-}
-
-/*Buttons*/
-.button {
- display: block;
- width: 200px;
- height: 40px;
- padding: 5px;
- outline: none;
-}
-
-.button .icon {
- width: 40px;
- height: 40px;
- float: left;
- margin-right: 10px;
-}
-
-.button .caption {
- display: block;
- font-size: 14px;
- font-weight: 600;
- color: #207FC5;
-}
-
-.button .description {
- font-size: 12px;
- color: #777;
- line-height: 13px;
-}
-
-.button:hover .caption,
-.button:focus .caption {
- text-decoration: underline;
-}
-
-.button.withBG {
- border: solid 1px #AAA;
- background-color: #EAEAEA;
- background-image: -moz-linear-gradient(to bottom, #EAEAEA, #E5E5E5, #EAEAEA);
- border-radius: 5px;
- box-shadow: inset 1px 1px 1px rgba(255, 255, 255, 0.3);
-}
-
-.button.withBG:hover {
- background-color: #E5E5E5;
- background-image: -moz-linear-gradient(to bottom, #E5E5E5, #E7E7E7, #E5E5E5);
-}
-
-.button.withBG:active {
- background-color: #DDD;
- box-shadow: 2px 2px 2px #999 inset;
- background-image: none;
-}
-
-/*Tooltip*/
-.tooltip {
- position: absolute;
- bottom: 30px;
- left: 0px;
-}
-
-.tooltip .inner {
- color: #FFF;
- background: rgba(0, 0, 0, 0.7);
- position: relative;
- width: 100px;
- border-radius: 5px;
-}
-
-.tooltip .inner:after {
- border-style: none solid solid solid;
- border-color: transparent rgba(0, 0, 0, 0.7) transparent transparent;
- border-width: 9px;
- position: absolute;
- top: 100%;
- left: 20px;
- content: "";
-}
-
-/*System notifications*/
-
-.sysmsg {
- display: block;
- margin: 10px 10px;
- padding: 5px;
- text-align: center;
- font-size: 14px;
- border-radius: 5px;
-}
-
-.sysmsg.error {
- border: solid 2px #C66;
- background: #FFD8D8;
- color: #C66;
-}
-
-/*Fixes*/
-a img {border: none;}
-a {text-decoration: none; color: inherit;}
-p { font-size: 13px; color: #777;}
\ No newline at end of file
diff --git a/assets/img/app.png b/assets/img/app.png
new file mode 100644
index 0000000..acc0514
Binary files /dev/null and b/assets/img/app.png differ
diff --git a/assets/img/link.png b/assets/img/link.png
new file mode 100644
index 0000000..7d3237f
Binary files /dev/null and b/assets/img/link.png differ
diff --git a/assets/img/logo-default.png b/assets/img/logo-default.png
new file mode 100644
index 0000000..9afd46e
Binary files /dev/null and b/assets/img/logo-default.png differ
diff --git a/assets/img/right-arrow.png b/assets/img/right-arrow.png
new file mode 100644
index 0000000..c733977
Binary files /dev/null and b/assets/img/right-arrow.png differ
diff --git a/assets/img/upload.svg b/assets/img/upload.svg
new file mode 100644
index 0000000..7260dcc
--- /dev/null
+++ b/assets/img/upload.svg
@@ -0,0 +1 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve"><path fill="none" stroke="rgba(0,0,0,.5)" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M16,6v20 M23.1,13.1L16,6c0,0-7.1,7.1-7.1,7.1"/></svg>
diff --git a/assets/img/user.png b/assets/img/user.png
new file mode 100644
index 0000000..a4940e9
Binary files /dev/null and b/assets/img/user.png differ
diff --git a/assets/js/.gitkeep b/assets/js/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/assets/js/app-create.js b/assets/js/app-create.js
new file mode 100644
index 0000000..f8aea98
--- /dev/null
+++ b/assets/js/app-create.js
@@ -0,0 +1,23 @@
+(function(){
+ 'use strict';
+ const
+ byid = id => document.getElementById(id),
+ $iconin = byid('icon-input'),
+ $iuwrap = byid('icon-upload-wrap');
+
+ $iconin.addEventListener('change',function(){
+ if (this.files && this.files[0]) {
+ $iuwrap.style.backgroundImage = '';
+ $iuwrap.classList.add('uploading');
+ let reader = new FileReader();
+
+ reader.onload = function(e){
+ $iuwrap.classList.remove('uploading');
+ $iuwrap.classList.add('uploaded');
+ $iuwrap.style.backgroundImage = `url("${e.target.result}")`;
+ };
+
+ reader.readAsDataURL(this.files[0]);
+ }
+ });
+})();
diff --git a/assets/js/app-create.min.js b/assets/js/app-create.min.js
new file mode 100644
index 0000000..1da8e06
--- /dev/null
+++ b/assets/js/app-create.min.js
@@ -0,0 +1,2 @@
+"use strict";!function(){var e=function(e){return document.getElementById(e)},t=e("icon-input"),a=e("icon-upload-wrap");t.addEventListener("change",function(){if(this.files&&this.files[0]){a.style.backgroundImage="",a.classList.add("uploading");var e=new FileReader;e.onload=function(e){a.classList.remove("uploading"),a.classList.add("uploaded"),a.style.backgroundImage='url("'+e.target.result+'")'},e.readAsDataURL(this.files[0])}})}();
+//# sourceMappingURL=app-create.min.js.map
diff --git a/assets/js/app-create.min.js.map b/assets/js/app-create.min.js.map
new file mode 100644
index 0000000..9123444
--- /dev/null
+++ b/assets/js/app-create.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["app-create.js"],"names":["byid","id","document","getElementById","$iconin","$iuwrap","addEventListener","this","files","style","backgroundImage","classList","add","reader","FileReader","onload","e","remove","target","result","readAsDataURL"],"mappings":"AAAA,cAAA,WAEC,GACCA,GAAO,SAAAC,GAAA,MAAMC,UAASC,eAAeF,IACrCG,EAAUJ,EAAK,cACfK,EAAUL,EAAK,mBAEhBI,GAAQE,iBAAiB,SAAS,WAC9B,GAAIC,KAAKC,OAASD,KAAKC,MAAM,GAAI,CAC7BH,EAAQI,MAAMC,gBAAkB,GAChCL,EAAQM,UAAUC,IAAI,YACtB,IAAIC,GAAS,GAAIC,WAEjBD,GAAOE,OAAS,SAASC,GACrBX,EAAQM,UAAUM,OAAO,aACzBZ,EAAQM,UAAUC,IAAI,YACtBP,EAAQI,MAAMC,gBAAd,QAAwCM,EAAEE,OAAOC,OAAjD,MAGJN,EAAOO,cAAcb,KAAKC,MAAM","file":"app-create.min.js","sourceRoot":"/assets/js"}
diff --git a/assets/js/app-detail.js b/assets/js/app-detail.js
new file mode 100644
index 0000000..047a703
--- /dev/null
+++ b/assets/js/app-detail.js
@@ -0,0 +1,187 @@
+(function(){
+ 'use strict';
+ const
+ byid = id => document.getElementById(id),
+ show = el => el.classList.remove('hidden'),
+ hide = el => el.classList.add('hidden'),
+ enable = el => el.removeAttribute('disabled'),
+ disable = el => el.setAttribute('disabled',''),
+ anmiationSupported = typeof document.createElement('div').animate === 'function',
+ $idcopy = byid('id-copy'),
+ $idcont = byid('id-container'),
+ $scopy = byid('secret-copy'),
+ $scont = byid('secret-container'),
+ $shidden = byid('secret-hidden'),
+ $svisible = byid('secret-visible'),
+ $namedisp = byid('name-display'),
+ $namein = byid('name-input'),
+ $changename = byid('change-name'),
+ $cancelname = byid('cancel-name'),
+ $namecont = byid('name-container'),
+ $icondisp = byid('icon-display'),
+ $iconin = byid('icon-input'),
+ $iuwrap = byid('icon-upload-wrap'),
+ $changeicon = byid('change-icon'),
+ $cancelicon = byid('cancel-icon');
+
+ // Copy any text to clipboard
+ // Must be called from within an event handler
+ const copy = (text, el) => {
+ if (!document.queryCommandSupported('copy')){
+ prompt('Copy with Ctrl+C, close with Enter', text);
+ return true;
+ }
+
+ let $helper = document.createElement('textarea'),
+ success = false;
+ $helper.style.opacity = 0;
+ $helper.style.width = 0;
+ $helper.style.height = 0;
+ $helper.style.position = 'fixed';
+ $helper.style.left = '-10px';
+ $helper.style.top = '50%';
+ $helper.style.display = 'block';
+ $helper.innerText = text;
+ document.getElementsByTagName('body')[0].appendChild($helper);
+ $helper.focus();
+ $helper.select();
+
+ try {
+ success = document.execCommand('copy');
+ } catch(err){}
+
+ $helper.parentNode.removeChild($helper);
+
+ if (!success){
+ prompt('Copy with Ctrl+C, close with Enter', text);
+ return;
+ }
+
+ if (el instanceof HTMLElement && anmiationSupported){
+ const currColor = window.getComputedStyle(el).getPropertyValue('color');
+ el.animate({
+ color: [currColor, '#000', currColor],
+ }, {
+ duration: 500,
+ });
+ }
+ };
+ const toggleContents = (el, between, animdur = 200) => {
+ if (anmiationSupported){
+ el.animate({
+ opacity: [1,0]
+ }, {
+ duration: animdur
+ }).onfinish = function(){
+ between();
+
+ el.animate({
+ opacity: [0,1]
+ }, {
+ duration: animdur
+ });
+ };
+ }
+ else between();
+ };
+
+ $scopy.addEventListener('click',function(e){
+ e.preventDefault();
+
+ copy($scont.getAttribute('data-actual'), $scopy);
+ });
+ $idcopy.addEventListener('click',function(e){
+ e.preventDefault();
+
+ copy($idcont.children[0].innerHTML, $idcopy);
+ });
+
+ let splacehold = false;
+ const setPlacehold = () => {
+ splacehold = $scont.innerHTML;
+ $scont.innerHTML = `<span class='fake-field'>${$scont.getAttribute('data-actual')}</span>`;
+ $shidden.classList.add('hidden');
+ $svisible.classList.remove('hidden');
+ };
+ $shidden.addEventListener('click',function(e){
+ if (!splacehold){
+ e.preventDefault();
+ toggleContents($scont, setPlacehold);
+ }
+ else return true;
+ });
+ const resetPlacehold = () => {
+ $scont.innerHTML = splacehold;
+ splacehold = false;
+ $svisible.classList.add('hidden');
+ $shidden.classList.remove('hidden');
+ };
+ $svisible.addEventListener('click',function(e){
+ if (splacehold){
+ e.preventDefault();
+ toggleContents($scont, resetPlacehold);
+ }
+ else return true;
+ });
+ $changename.addEventListener('click',function(e){
+ e.preventDefault();
+
+ toggleContents($namecont, function(){
+ hide($namedisp);
+ hide($changename);
+ $namein.value = $namedisp.innerHTML;
+ enable($namein);
+ show($namein.parentNode);
+ show($cancelname);
+ });
+ });
+ $cancelname.addEventListener('click',function(e){
+ e.preventDefault();
+
+ toggleContents($namecont, function(){
+ hide($namein.parentNode);
+ disable($namein);
+ hide($cancelname);
+ show($namedisp);
+ show($changename);
+ });
+ });
+
+ $changeicon.addEventListener('click',function(e){
+ e.preventDefault();
+
+ enable($iconin);
+ show($iuwrap);
+ show($cancelicon);
+ hide($icondisp);
+ hide($changeicon);
+ });
+ $cancelicon.addEventListener('click',function(e){
+ e.preventDefault();
+
+ hide($iuwrap);
+ hide($cancelicon);
+ disable($iconin);
+ $iconin.value = '';
+ $iuwrap.style.backgroundImage = '';
+ $iuwrap.classList.remove('uploading');
+ $iuwrap.classList.remove('uploaded');
+ show($icondisp);
+ show($changeicon);
+ });
+ $iconin.addEventListener('change',function(){
+ if (this.files && this.files[0]) {
+ $iuwrap.style.backgroundImage = '';
+ $iuwrap.classList.add('uploading');
+ let reader = new FileReader();
+
+ reader.onload = function(e){
+ $iuwrap.classList.remove('uploading');
+ $iuwrap.classList.add('uploaded');
+ $iuwrap.style.backgroundImage = `url("${e.target.result}")`;
+ };
+
+ reader.readAsDataURL(this.files[0]);
+ }
+ });
+})();
diff --git a/assets/js/app-detail.min.js b/assets/js/app-detail.min.js
new file mode 100644
index 0000000..57ed8b4
--- /dev/null
+++ b/assets/js/app-detail.min.js
@@ -0,0 +1,2 @@
+"use strict";!function(){var e=function(e){return document.getElementById(e)},t=function(e){return e.classList.remove("hidden")},n=function(e){return e.classList.add("hidden")},i=function(e){return e.removeAttribute("disabled")},a=function(e){return e.setAttribute("disabled","")},c="function"==typeof document.createElement("div").animate,r=e("id-copy"),o=e("id-container"),d=e("secret-copy"),s=e("secret-container"),l=e("secret-hidden"),u=e("secret-visible"),p=e("name-display"),f=e("name-input"),v=e("change-name"),m=e("cancel-name"),y=e("name-container"),L=e("icon-display"),h=e("icon-input"),g=e("icon-upload-wrap"),E=e("change-icon"),k=e("cancel-icon"),b=function(e,t){if(!document.queryCommandSupported("copy"))return prompt("Copy with Ctrl+C, close with Enter",e),!0;var n=document.createElement("textarea"),i=!1;n.style.opacity=0,n.style.width=0,n.style.height=0,n.style.position="fixed",n.style.left="-10px",n.style.top="50%",n.style.display="block",n.innerText=e,document.getElementsByTagName("body")[0].appendChild(n),n.focus(),n.select();try{i=document.execCommand("copy")}catch(a){}if(n.parentNode.removeChild(n),!i)return void prompt("Copy with Ctrl+C, close with Enter",e);if(t instanceof HTMLElement&&c){var r=window.getComputedStyle(t).getPropertyValue("color");t.animate({color:[r,"#000",r]},{duration:500})}},C=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:200;c?e.animate({opacity:[1,0]},{duration:n}).onfinish=function(){t(),e.animate({opacity:[0,1]},{duration:n})}:t()};d.addEventListener("click",function(e){e.preventDefault(),b(s.getAttribute("data-actual"),d)}),r.addEventListener("click",function(e){e.preventDefault(),b(o.children[0].innerHTML,r)});var w=!1,D=function(){w=s.innerHTML,s.innerHTML="<span class='fake-field'>"+s.getAttribute("data-actual")+"</span>",l.classList.add("hidden"),u.classList.remove("hidden")};l.addEventListener("click",function(e){return!!w||(e.preventDefault(),void C(s,D))});var T=function(){s.innerHTML=w,w=!1,u.classList.add("hidden"),l.classList.remove("hidden")};u.addEventListener("click",function(e){return!w||(e.preventDefault(),void C(s,T))}),v.addEventListener("click",function(e){e.preventDefault(),C(y,function(){n(p),n(v),f.value=p.innerHTML,i(f),t(f.parentNode),t(m)})}),m.addEventListener("click",function(e){e.preventDefault(),C(y,function(){n(f.parentNode),a(f),n(m),t(p),t(v)})}),E.addEventListener("click",function(e){e.preventDefault(),i(h),t(g),t(k),n(L),n(E)}),k.addEventListener("click",function(e){e.preventDefault(),n(g),n(k),a(h),h.value="",g.style.backgroundImage="",g.classList.remove("uploading"),g.classList.remove("uploaded"),t(L),t(E)}),h.addEventListener("change",function(){if(this.files&&this.files[0]){g.style.backgroundImage="",g.classList.add("uploading");var e=new FileReader;e.onload=function(e){g.classList.remove("uploading"),g.classList.add("uploaded"),g.style.backgroundImage='url("'+e.target.result+'")'},e.readAsDataURL(this.files[0])}})}();
+//# sourceMappingURL=app-detail.min.js.map
diff --git a/assets/js/app-detail.min.js.map b/assets/js/app-detail.min.js.map
new file mode 100644
index 0000000..e22f4ee
--- /dev/null
+++ b/assets/js/app-detail.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["app-detail.js"],"names":["byid","id","document","getElementById","show","el","classList","remove","hide","add","enable","removeAttribute","disable","setAttribute","anmiationSupported","createElement","animate","$idcopy","$idcont","$scopy","$scont","$shidden","$svisible","$namedisp","$namein","$changename","$cancelname","$namecont","$icondisp","$iconin","$iuwrap","$changeicon","$cancelicon","copy","text","queryCommandSupported","prompt","$helper","success","style","opacity","width","height","position","left","top","display","innerText","getElementsByTagName","appendChild","focus","select","execCommand","err","parentNode","removeChild","HTMLElement","currColor","window","getComputedStyle","getPropertyValue","color","duration","toggleContents","between","animdur","arguments","length","undefined","onfinish","addEventListener","e","preventDefault","getAttribute","children","innerHTML","splacehold","setPlacehold","resetPlacehold","value","backgroundImage","this","files","reader","FileReader","onload","target","result","readAsDataURL"],"mappings":"AAAA,cAAA,WAEC,GACCA,GAAO,SAAAC,GAAA,MAAMC,UAASC,eAAeF,IACrCG,EAAO,SAAAC,GAAA,MAAMA,GAAGC,UAAUC,OAAO,WACjCC,EAAO,SAAAH,GAAA,MAAMA,GAAGC,UAAUG,IAAI,WAC9BC,EAAS,SAAAL,GAAA,MAAMA,GAAGM,gBAAgB,aAClCC,EAAU,SAAAP,GAAA,MAAMA,GAAGQ,aAAa,WAAW,KAC3CC,EAAsE,kBAA1CZ,UAASa,cAAc,OAAOC,QAC1DC,EAAUjB,EAAK,WACfkB,EAAUlB,EAAK,gBACfmB,EAASnB,EAAK,eACdoB,EAASpB,EAAK,oBACdqB,EAAWrB,EAAK,iBAChBsB,EAAYtB,EAAK,kBACjBuB,EAAYvB,EAAK,gBACjBwB,EAAUxB,EAAK,cACfyB,EAAczB,EAAK,eACnB0B,EAAc1B,EAAK,eACnB2B,EAAY3B,EAAK,kBACjB4B,EAAY5B,EAAK,gBACjB6B,EAAU7B,EAAK,cACf8B,EAAU9B,EAAK,oBACf+B,EAAc/B,EAAK,eACnBgC,EAAchC,EAAK,eAIdiC,EAAO,SAACC,EAAM7B,GACnB,IAAKH,SAASiC,sBAAsB,QAEnC,MADAC,QAAO,qCAAsCF,IACtC,CAGR,IAAIG,GAAUnC,SAASa,cAAc,YACpCuB,GAAU,CACXD,GAAQE,MAAMC,QAAU,EACxBH,EAAQE,MAAME,MAAQ,EACtBJ,EAAQE,MAAMG,OAAS,EACvBL,EAAQE,MAAMI,SAAW,QACzBN,EAAQE,MAAMK,KAAO,QACrBP,EAAQE,MAAMM,IAAM,MACpBR,EAAQE,MAAMO,QAAU,QACxBT,EAAQU,UAAYb,EACpBhC,SAAS8C,qBAAqB,QAAQ,GAAGC,YAAYZ,GACrDA,EAAQa,QACRb,EAAQc,QAER,KACCb,EAAUpC,SAASkD,YAAY,QAC9B,MAAMC,IAIR,GAFAhB,EAAQiB,WAAWC,YAAYlB,IAE1BC,EAEJ,WADAF,QAAO,qCAAsCF,EAI9C,IAAI7B,YAAcmD,cAAe1C,EAAmB,CACnD,GAAM2C,GAAYC,OAAOC,iBAAiBtD,GAAIuD,iBAAiB,QAC/DvD,GAAGW,SACI6C,OAAQJ,EAAW,OAAQA,KAE3BK,SAAU,QAIbC,EAAiB,SAAC1D,EAAI2D,GAA2B,GAAlBC,GAAkBC,UAAAC,OAAA,GAAAC,SAAAF,UAAA,GAAAA,UAAA,GAAR,GAC1CpD,GACHT,EAAGW,SACFwB,SAAU,EAAE,KAEZsB,SAAUG,IACRI,SAAW,WACbL,IAEA3D,EAAGW,SACFwB,SAAU,EAAE,KAEZsB,SAAUG,KAIRD,IAGN7C,GAAOmD,iBAAiB,QAAQ,SAASC,GACxCA,EAAEC,iBAEFvC,EAAKb,EAAOqD,aAAa,eAAgBtD,KAE1CF,EAAQqD,iBAAiB,QAAQ,SAASC,GACzCA,EAAEC,iBAEFvC,EAAKf,EAAQwD,SAAS,GAAGC,UAAW1D,IAGrC,IAAI2D,IAAa,EACXC,EAAe,WACpBD,EAAaxD,EAAOuD,UACpBvD,EAAOuD,UAAP,4BAA+CvD,EAAOqD,aAAa,eAAnE,UACApD,EAASf,UAAUG,IAAI,UACvBa,EAAUhB,UAAUC,OAAO,UAE5Bc,GAASiD,iBAAiB,QAAQ,SAASC,GAC1C,QAAKK,IACJL,EAAEC,qBACFT,GAAe3C,EAAQyD,KAIzB,IAAMC,GAAiB,WACtB1D,EAAOuD,UAAYC,EACnBA,GAAa,EACbtD,EAAUhB,UAAUG,IAAI,UACxBY,EAASf,UAAUC,OAAO,UAE3Be,GAAUgD,iBAAiB,QAAQ,SAASC,GAC3C,OAAIK,IACHL,EAAEC,qBACFT,GAAe3C,EAAQ0D,MAIzBrD,EAAY6C,iBAAiB,QAAQ,SAASC,GAC7CA,EAAEC,iBAEFT,EAAepC,EAAW,WACzBnB,EAAKe,GACLf,EAAKiB,GACLD,EAAQuD,MAAQxD,EAAUoD,UAC1BjE,EAAOc,GACPpB,EAAKoB,EAAQ8B,YACblD,EAAKsB,OAGPA,EAAY4C,iBAAiB,QAAQ,SAASC,GAC7CA,EAAEC,iBAEFT,EAAepC,EAAW,WACzBnB,EAAKgB,EAAQ8B,YACb1C,EAAQY,GACRhB,EAAKkB,GACLtB,EAAKmB,GACLnB,EAAKqB,OAIPM,EAAYuC,iBAAiB,QAAQ,SAASC,GAC7CA,EAAEC,iBAEF9D,EAAOmB,GACPzB,EAAK0B,GACL1B,EAAK4B,GACLxB,EAAKoB,GACLpB,EAAKuB,KAENC,EAAYsC,iBAAiB,QAAQ,SAASC,GAC7CA,EAAEC,iBAEFhE,EAAKsB,GACLtB,EAAKwB,GACLpB,EAAQiB,GACRA,EAAQkD,MAAQ,GACVjD,EAAQS,MAAMyC,gBAAkB,GAChClD,EAAQxB,UAAUC,OAAO,aACzBuB,EAAQxB,UAAUC,OAAO,YAC/BH,EAAKwB,GACLxB,EAAK2B,KAENF,EAAQyC,iBAAiB,SAAS,WAC9B,GAAIW,KAAKC,OAASD,KAAKC,MAAM,GAAI,CAC7BpD,EAAQS,MAAMyC,gBAAkB,GAChClD,EAAQxB,UAAUG,IAAI,YACtB,IAAI0E,GAAS,GAAIC,WAEjBD,GAAOE,OAAS,SAASd,GACrBzC,EAAQxB,UAAUC,OAAO,aACzBuB,EAAQxB,UAAUG,IAAI,YACtBqB,EAAQS,MAAMyC,gBAAd,QAAwCT,EAAEe,OAAOC,OAAjD,MAGJJ,EAAOK,cAAcP,KAAKC,MAAM","file":"app-detail.min.js","sourceRoot":"/assets/js"}
\ No newline at end of file
diff --git a/assets/js/avatar.js b/assets/js/avatar.js
new file mode 100644
index 0000000..5a162a6
--- /dev/null
+++ b/assets/js/avatar.js
@@ -0,0 +1,40 @@
+(function(){
+ 'use strict';
+
+ let choseBtn = document.querySelector("#imgSubmit"),
+ imgDisplay = document.querySelector("#imgDisplay"),
+ imgInp = document.querySelector("#imgInp");
+
+ /*
+ * Define a listener for the input, once the image selected was changed, we
+ * will load it into the window.
+ */
+ imgInp.addEventListener('change',function(){
+ if (this.files && this.files[0]) {
+ let reader = new FileReader();
+
+ reader.onload = function (e) {
+ let image = new Image();
+ image.src = e.target.result;
+ image.className = 'user-icon full-width square';
+ image.style.marginTop = '10px';
+ image.style.maxHeight = '300px';
+
+ imgDisplay.appendChild(image);
+ };
+
+ imgDisplay.innerHTML = '';
+ reader.readAsDataURL(this.files[0]);
+ }
+
+ choseBtn.disabled = !this.value;
+ });
+
+ imgDisplay.addEventListener('click', function () {
+ imgInp.click();
+ }, false);
+
+ imgInp.style.display = 'none';
+
+ choseBtn.disabled = true;
+})();
diff --git a/assets/js/avatar.min.js b/assets/js/avatar.min.js
new file mode 100644
index 0000000..7d07e12
--- /dev/null
+++ b/assets/js/avatar.min.js
@@ -0,0 +1,2 @@
+"use strict";!function(){var e=document.querySelector("#imgSubmit"),i=document.querySelector("#imgDisplay");document.querySelector("#imgInp").addEventListener("change",function(){if(this.files&&this.files[0]){var t=new FileReader;t.onload=function(e){var t=new Image;t.src=e.target.result,t.className="user-icon full-width square",t.style.marginTop="10px",t.style.maxHeight="300px",i.appendChild(t)},i.innerHTML="",t.readAsDataURL(this.files[0])}e.disabled=!this.value});e.disabled=!0}();
+//# sourceMappingURL=avatar.min.js.map
diff --git a/assets/js/avatar.min.js.map b/assets/js/avatar.min.js.map
new file mode 100644
index 0000000..b6f2b28
--- /dev/null
+++ b/assets/js/avatar.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["avatar.js"],"names":["choseBtn","document","querySelector","imgDisplay","addEventListener","this","files","reader","FileReader","onload","e","image","Image","src","target","result","className","style","marginTop","maxHeight","appendChild","innerHTML","readAsDataURL","disabled","value"],"mappings":"AAAA,cAAA,WAGC,GAAIA,GAAWC,SAASC,cAAc,cACrCC,EAAaF,SAASC,cAAc,cAC3BD,UAASC,cAAc,WAAWE,iBAAiB,SAAS,WACjE,GAAIC,KAAKC,OAASD,KAAKC,MAAM,GAAI,CAC7B,GAAIC,GAAS,GAAIC,WAEjBD,GAAOE,OAAS,SAAUC,GACtB,GAAIC,GAAQ,GAAIC,MAChBD,GAAME,IAAMH,EAAEI,OAAOC,OACrBJ,EAAMK,UAAY,8BAClBL,EAAMM,MAAMC,UAAY,OACxBP,EAAMM,MAAME,UAAY,QAExBhB,EAAWiB,YAAYT,IAGxBR,EAAWkB,UAAY,GAC1Bd,EAAOe,cAAcjB,KAAKC,MAAM,IAGpCN,EAASuB,UAAYlB,KAAKmB,OAG/BxB,GAASuB,UAAW","file":"avatar.min.js","sourceRoot":"/assets/js"}
\ No newline at end of file
diff --git a/assets/js/core/debounce.js b/assets/js/core/debounce.js
new file mode 100644
index 0000000..11efab4
--- /dev/null
+++ b/assets/js/core/debounce.js
@@ -0,0 +1,82 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+depend([], function() {
+
+
+ /*
+ * This helper allows the application to define listeners that will prevent
+ * the application from hogging system resources when a lot of events are
+ * fired.
+ *
+ * @param {type} fn
+ * @returns {Function}
+ */
+ var debounce = function (fn, interval) {
+ /*
+ * The timeout variable is used to determine whether the debounce has blocked
+ * the execution of further listeners.
+ */
+ var timeout = undefined;
+
+ /*
+ * We cache the return value of the debounced function. For some applications,
+ * like listeners, this is rather irrelevant.
+ *
+ * This has more application when you intend to execute a function that is
+ * costly to the browser but it's return value is predictable enough that
+ * being run once should yield consistent results.
+ *
+ * For example, determining the bounding box of an element is extremely taxing
+ * on the browser. But, our elements rarely move around enough to justify
+ * the calculation regularly.
+ */
+ var returnv = undefined;
+
+ return function () {
+ if (returnv === undefined) { return returnv = fn.apply(window, arguments); }
+ if (timeout) { return returnv; }
+
+ var args = arguments;
+ var callback = function () {
+ returnv = fn.apply(window, args) || null;
+ timeout = undefined;
+ };
+
+ if (window.requestAnimationFrame && !interval) { timeout = window.requestAnimationFrame(callback); }
+ else { timeout = setTimeout(callback, interval || 50); }
+
+ return returnv;
+ };
+ };
+
+ if (window.m3w === undefined) { window.m3w = {}; }
+ if (window.m3w.core === undefined) { window.m3w.core = {}; }
+
+ window.m3w.core.debounce = debounce;
+
+ return debounce;
+
+});
\ No newline at end of file
diff --git a/assets/js/depend.js b/assets/js/depend.js
new file mode 100644
index 0000000..7d40a07
--- /dev/null
+++ b/assets/js/depend.js
@@ -0,0 +1,307 @@
+/* global HTMLElement */
+
+(function () {
+
+ var modules = [];
+ var pending = [];
+
+ /**
+ * The last module imported. If an onload comes around we will properly name
+ * it and push it to our list of sorted dependencies.
+ *
+ * @type Module
+ */
+ var last = null;
+
+ /**
+ * The base URL for the JS files to be located.
+ *
+ * @todo Replace with a proper router for multiple locations and whatnot.
+ * @type String|url
+ */
+ var router = function(e) { return e + '.js'; };
+
+ /**
+ * Provides a standard behavior for attaching listeners to a HTMLElement
+ * inside the library. This also provides fallbacks for browsers that do not
+ * support addEventListener or any listener at all.
+ *
+ * @param {Object} src
+ * @param {string} evt
+ * @param {Function} callback
+ * @returns {undefined}
+ */
+ function on(src, evt, callback) {
+
+ /*
+ * If the browser supports addeventlistener we can stop right there, since
+ * we do already have support for listeners the way we want them.
+ */
+ if (window.addEventListener && src instanceof HTMLElement) {
+ return src.addEventListener(evt, callback, false);
+ }
+
+ /*
+ * Old versions (ancient by now) do support the attachEvent alternative to
+ * addEventlistener, while it is essentially identical, it has a different
+ * syntax.
+ */
+ if (window.attachEvent && src instanceof HTMLElement) {
+ return src.attachEvent('on' + evt, callback);
+ }
+
+ /*
+ * This will locate a onLoad, for example, and stack it. Should provide fallback
+ * even for the most primitive of browsers.
+ *
+ * Using this, we can also generate stacked events for any objects that are
+ * not HTMLElements and therefore do not support addEventlistener.
+ */
+ var attr = 'on' + evt;
+ var prev = src[attr] !== undefined ? src[attr] : null;
+ src[attr] = function (e) {
+ return callback(e) !== false && (!prev || prev(e));
+ };
+ }
+
+ function available(name) {
+ for (var i = 0; i < modules.length; i++) {
+ if (modules[i].getName() === name) {
+ return modules[i];
+ }
+ }
+
+ return null;
+ }
+
+ function isQueued(script) {
+ for (var i = 0; i < pending.length; i++) {
+ if (pending[i].getAttribute('data-src') === script) {
+ return pending[i];
+ }
+ }
+ }
+
+ function script(src) {
+ /*
+ * We create a script tag so the user gets a feeling for what he imported.
+ * This allows the browser to expose proper debugging.
+ *
+ * @type @exp;document@call;createElement
+ */
+ var script = document.createElement('script');
+ script.src = router(src);
+ script.async = true;
+ script.type = 'text/javascript';
+ script.setAttribute('data-src', src);
+
+ return script;
+ }
+
+ function Dependency(loader, identifier) {
+
+ this.callable = undefined;
+
+ this.load = function () {
+ var self = this;
+
+ if (available(identifier)) {
+ available(identifier).onReady(function() {
+ self.callable = this.getCallable();
+ loader.notify();
+ });
+ return;
+ }
+
+ if (isQueued(identifier)) {
+ var tag = isQueued(identifier);
+ }
+ else {
+ var tag = script(identifier);
+ }
+
+ on(tag, 'load', function (e) {
+ /*
+ * This function is called once per module awaiting this script's end,
+ * which implies that the first listener will basically "consume" last
+ * and therefore, subsequent listeners will have to retrieve the
+ * appropriate module.
+ */
+ var module = last? last : available(e.target.getAttribute('data-src'));
+
+ //We just received the onload event for the script the browser was compiling.
+ //This means we can use the script's name to address the module it just compiled
+ console.log(e.target.getAttribute('data-src'));
+ module.setName(e.target.getAttribute('data-src'));
+
+ /*
+ * Drop the module we were loading from the list of modules we're waiting for
+ */
+ if (pending.indexOf(this) !== -1) {
+ pending.splice(pending.indexOf(this), 1);
+ last = null;
+ }
+
+ /*
+ * Since we now have a module we can basically apply to be notified
+ * once the module is compiled and ready to be used.
+ *
+ * When the module is ready, the dependency will retrieve it's callable
+ * (which is not required to be a function) and notifies the loader
+ * that the dependency has been resolved.
+ */
+ module.onReady(function () {
+ self.callable = module.getCallable();
+ loader.notify();
+ });
+ });
+
+ on (tag, 'error', function (e) {
+ console.error('Error loading module ' + e.target.getAttribute('data-src'));
+ console.log('Dependency loading failed. Depending modules will not be initialized.');
+
+ if (pending.indexOf(this) !== -1) {
+ pending.splice(pending.indexOf(this), 1);
+ last = null;
+ }
+ });
+
+ if (!tag.parentNode) {
+ document.head.appendChild(tag);
+ pending.push(tag);
+ }
+ };
+ }
+
+ function DependencyLoader(d, callback) {
+
+
+ var dependencies = d.map(function (e) {
+ return new Dependency(this, e);
+ }, this);
+
+ var total = dependencies.length;
+ var progress = 0;
+
+ this.notify = function () {
+ progress++;
+
+ if (progress === total) {
+ callback(dependencies.map(function (e) { return e.callable; }));
+ }
+ };
+
+ if (0 === total) {
+ /*
+ * Since there are no dependencies, the system will need to load none and
+ * can therefore immediately proceed to calling the provided callback.
+ */
+ callback([]);
+ }
+
+ for (var i = 0; i < total; i++) {
+ dependencies[i].load();
+ }
+ }
+
+ function Module(name, dependencies, definition) {
+
+ var self = this;
+
+ this.name = name;
+ this.callable = undefined;
+ this.resolved = false;
+ this.listeners = [];
+
+ this.init = function () {
+ new DependencyLoader(dependencies, function (deps) {
+ try {
+ self.callable = definition.apply(null, deps);
+ } catch (e) {
+ console.log('Error initializing module. Error was: ');
+ console.error(e);
+ }
+ self.resolved = true;
+ self.onReady();
+ });
+ };
+
+ this.onReady = function (param) {
+ if (param) {
+ this.listeners.push(param);
+ }
+
+ if (this.resolved) {
+ for (var i = 0; i < this.listeners.length; i++) {
+ this.listeners[i].call(this);
+ }
+
+ this.listeners = [];
+ }
+ };
+ }
+
+ Module.prototype = {
+ setName: function (set) {
+ this.name = set;
+ },
+
+ getName: function () {
+ return this.name;
+ },
+
+ getCallable: function () {
+ return this.callable;
+ }
+ };
+
+
+ function depend(name, dependencies, definition) {
+
+ /*
+ * Check if the name is missing first. This will cause us to wait for onload
+ * to name this puppy.
+ */
+ if (!definition && typeof name !== 'string') {
+ definition = dependencies;
+ dependencies = name;
+ name = null;
+ }
+
+ /*
+ * The dependencies are also optional in JSDepend, so we're gonna keep the
+ * interface compatible.
+ */
+ if (typeof dependencies === 'function') {
+ definition = dependencies;
+ dependencies = [];
+ }
+
+
+ /*
+ * We return a module. This object will then be named by the onload of our
+ * script when compiled.
+ */
+ var module = new Module(name, dependencies, definition);
+ modules.push(module);
+ last = name ? null : module;
+
+ /*
+ * Move the execution of the module to a clean stack trace. This prevents
+ * the stack from becoming to unwieldy and errors from stopping the execution
+ * of properly working modules.
+ *
+ */
+ setTimeout(function() {module.init();}, 0);
+
+ return module;
+ }
+
+ /*
+ * Export the appropriate variable to the browser's context. This allows the
+ * developer to use the class.
+ */
+ window.depend = depend;
+ window.depend.setRouter = function(r) { router = r; };
+
+}());
diff --git a/assets/js/depend/router.js b/assets/js/depend/router.js
new file mode 100644
index 0000000..82757fa
--- /dev/null
+++ b/assets/js/depend/router.js
@@ -0,0 +1,157 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * Provides routing for the depend.js dependency loader. This allows applications
+ * to map namespaces or certain suffixes to certain locations.
+ *
+ * This router can generally not be loaded through depend itself. Since usually,
+ * the router is required to even load components.
+ *
+ * Instead, it will register itself. Therefore allowing to load it in a "classic"
+ * fashion and then register rules and load the actual dependencies.
+ */
+depend('depend/router', [], function () {
+
+ "use strict";
+
+ function Router() {
+ this.rules = [];
+ this.catchAll = undefined;
+
+ }
+
+ Router.prototype = {
+ rewrite: function (url) {
+ for (var i in this.rules) {
+ if (this.rules[i].matches(url)) { return this.rules[i].rewrite(url); }
+ }
+
+ return this.catchAll? this.catchAll.rewrite(url) : null;
+ },
+
+ startsWith: function(string) {
+ var rule = new Rule(new StartsWithCondition(string));
+ this.rules.push(rule);
+ return rule;
+ },
+
+ endsWith: function(string) {
+ var rule = new Rule(new EndsWithCondition(string));
+ this.rules.push(rule);
+ return rule;
+ },
+
+ equals: function(string) {
+ var rule = new Rule(new EqualsCondition(string));
+ this.rules.push(rule);
+ return rule;
+ },
+
+ all: function() {
+ var rule = new Rule(new PermanentCondition());
+ this.catchAll = rule;
+ return rule;
+ }
+ };
+
+ function Rule(condition) {
+ /*
+ * If the condition is satisfied, the router calls the target with the result.
+ */
+ this.conditions = [condition];
+ this.target = undefined;
+
+
+ }
+
+ Rule.prototype = {
+ to: function (target) {
+ this.target = target;
+ return this;
+ },
+
+ and: function (condition) {
+ this.conditions.push(condition);
+ return this;
+ },
+
+ matches: function (string) {
+ var matches = true;
+
+ for (var i in this.conditions) {
+ matches = matches && this.conditions[i].satisfiedBy(string);
+ }
+
+ return matches;
+ },
+
+ rewrite: function (string) {
+ return this.target? this.target(string) : null;
+ },
+
+ rules: {
+ starts: StartsWithCondition,
+ ends: EndsWithCondition,
+ equals: EqualsCondition
+ }
+ };
+
+ function StartsWithCondition(search) {
+
+ this.satisfiedBy = function (string) {
+ return string.indexOf(search) === 0;
+ };
+ }
+
+ function EndsWithCondition(search) {
+
+ this.satisfiedBy = function (string) {
+ return string.lastIndexOf(search) + search.length === string.length;
+ };
+ }
+
+ function EqualsCondition(search) {
+ this.satisfiedBy = function (string) {
+ return search === string;
+ };
+ }
+
+ function PermanentCondition() {
+ this.satisfiedBy = function () {
+ return true;
+ };
+ }
+
+ /*
+ * Instance the router and register it with the dependency system.
+ */
+ var router = new Router();
+ window.depend.setRouter(function (e) { return router.rewrite(e); });
+
+ /*
+ * Return it, this way we can depend on the router to configure it.
+ */
+ return router;
+});
\ No newline at end of file
diff --git a/assets/js/dials.js b/assets/js/dials.js
new file mode 100644
index 0000000..14a47e7
--- /dev/null
+++ b/assets/js/dials.js
@@ -0,0 +1,47 @@
+(function () {
+ var dials = document.querySelectorAll('.dials');
+ var curtain = document.body.appendChild(document.createElement('div'));
+ var current = null;
+
+ curtain.className = 'dials-curtain dnd';
+ curtain.style.display = 'none';
+
+ var hideCurtain = function () {
+ curtain.classList.add('dnd');
+ setTimeout(function () { curtain.style.display = 'none'; }, 300);
+ };
+
+ var showCurtain = function (d) {
+ setTimeout(function () {
+ curtain.classList.remove('dnd');
+ }, 50);
+
+ d.style.display = 'block';
+ curtain.style.display = 'block';
+ };
+
+ for (var i = 0; i < dials.length; i++) {
+ var p = dials[i].parentNode;
+ var t = p.appendChild(document.createElement('span'));
+ var d = p.querySelector('.dials');
+
+ p.classList.add('has-dials');
+ t.classList.add('dial-toggle', 'medium', 'narrow');
+
+ d.addEventListener('click', function (e) { e.stopPropagation(); }, false);
+
+ t.addEventListener('click', function (p, t, d) {
+ return function (e) {
+ showCurtain(d);
+ current = d;
+ e.stopPropagation();
+ };
+ } (p, t, d), false);
+ }
+
+ document.addEventListener('click', function () {
+ if (current) { current.style.display = 'none'; }
+ hideCurtain();
+ current = null;
+ }, false);
+}());
\ No newline at end of file
diff --git a/assets/js/m3 b/assets/js/m3
new file mode 160000
index 0000000..c793235
--- /dev/null
+++ b/assets/js/m3
@@ -0,0 +1 @@
+Subproject commit c7932350f71c5cb54a0bc7cc047f0708c8544bbe
diff --git a/assets/js/sticky.js b/assets/js/sticky.js
new file mode 100644
index 0000000..15f294f
--- /dev/null
+++ b/assets/js/sticky.js
@@ -0,0 +1,304 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+/**
+ *
+ * @todo This code is a major mess, but it seems to work reliably enough for now.
+ * Needs refactoring.
+ *
+ * @returns {undefined}
+ */
+depend(['core/debounce'], function (debounce) {
+
+ "use strict";
+
+ /**
+ *
+ * @type Array
+ */
+ var registered = [];
+ var offset = {x : window.pageXOffset, y : window.pageYOffset };
+
+ /*
+ * Stuck elements are those two that are either pinned to the top or the bottom
+ * of the page.
+ *
+ * @param {type} position
+ * @returns {stickyL#33.Stuck}
+ */
+ var Pin = function (position) {
+ var html = undefined;
+ var wrapper = undefined;
+ var child = undefined;
+
+ this.setChild = function (c, ctx, next) {
+
+ if (c) {
+
+ if (child !== c) {
+ if (html) {
+ html.style = null;
+ wrapper.style = null;
+
+ //wrapper.style.display = 'inline-block';
+ //wrapper.style.width = '100%';
+ console.log(wrapper.style);
+ }
+
+ wrapper = c.getHTML();
+ html = wrapper.firstChild;
+
+ c.getHTML().style.display = 'inline-block';
+ c.getHTML().style.height = c.getBoundaries().getH() + 'px';
+ c.getHTML().style.width = c.getBoundaries().getW() + 'px';
+
+ html.style.position = 'fixed';
+ html.style.display = 'inline-block';
+ html.style[position] = '0';
+ html.style.height = c.getBoundaries().getH() + 'px';
+ html.style.width = c.getBoundaries().getW() + 'px';
+ html.style.zIndex = 5;
+ html.style.background = ctx.getBackground();
+
+ }
+
+ if (position === 'top') {
+ html.style.top = Math.min(
+ 0,
+ next? (next.getBoundaries().getScreenOffsetTop() - c.getBoundaries().getH()) : 0,
+ ctx.getBoundaries().getY() + ctx.getBoundaries().getH() - c.getBoundaries().getH()
+ ) + 'px';
+ }
+
+ if (position === 'bottom') {
+ html.style.bottom = Math.min(
+ 0,
+ next? next.getBoundaries().getScreenOffsetBottom() - c.getBoundaries().getH(): 0,
+ window.innerHeight - ctx.getBoundaries().getScreenOffsetTop() - c.getBoundaries().getH()
+ ) + 'px';
+ }
+ }
+ else if (html){
+ /*
+ * No new element is found, we can therefore replace the original styles
+ * to the wrappers and unset them.
+ */
+ html.style = null;
+ wrapper.style = null;
+
+ //wrapper.style.display = 'inline-block';
+ //wrapper.style.width = '100%';
+
+ child = undefined;
+ html = undefined;
+ }
+
+ child = c;
+ };
+ };
+
+ /**
+ *
+ * @type Object
+ */
+ var pinned = {
+ top: new Pin('top'),
+ bottom: new Pin('bottom')
+ };
+
+ var Sticky = function (element, context, direction) {
+
+ this.getElement = function () { return element; };
+ this.getContext = function () { return context; };
+ this.getDirection = function () { return direction || 'top'; };
+
+ registered.push(this);
+ };
+
+ var Context = function (element) {
+
+ this.getElement = function () {
+ return element;
+ };
+ };
+
+ var Boundaries = function (x, y, h, w) {
+
+ this.getX = function () { return x; };
+ this.getY = function () { return y; };
+ this.getH = function () { return h; };
+ this.getW = function () { return w; };
+
+ this.onscreen = function () {
+ return (offset.x < x + w && offset.x + window.innerWidth > x) &&
+ (offset.y < y + h && offset.y + window.innerHeight > y);
+ };
+
+ this.getScreenOffsetTop = function () {
+ return y - offset.y;
+ };
+
+ this.getScreenOffsetBottom = function () {
+ return offset.y + window.innerHeight - (y + h);
+ };
+
+ this.getScreenOffsetLeft = function () {
+ return x - offset.x;
+ };
+ };
+
+ var Element = function (original) {
+ /*
+ * These lines prevent the system from collapsing the borders.
+ */
+ //original.style.display = 'inline-block';
+ //original.style.width = '100%';
+
+ this.getBoundaries = debounce(function () {
+ var box = original.getBoundingClientRect();
+
+ return new Boundaries(
+ box.left + window.pageXOffset,
+ box.top + window.pageYOffset,
+ box.height,
+ box.width
+ );
+ }, 2000);
+
+ this.getBackground = function() {
+ return '#fff'; //TODO: Implement
+ };
+
+ this.getHTML = function() {
+ return original;
+ };
+ };
+
+
+ var findContext = function (e) {
+ if (e === document.body) { return e; }
+ if (e.hasAttribute('data-sticky-context')) { return e; }
+
+ return findContext(e.parentNode);
+ };
+
+ var wrap = function (element) {
+ var wrapper = document.createElement('div');
+ element.parentNode.insertBefore(wrapper, element);
+ wrapper.appendChild(element);
+
+ return wrapper;
+ };
+
+ /*
+ * Register a listener to defer all scroll listening. When the user scrolls,
+ * the listener will check which elements it should pin to the top and which
+ * it should leave behind.
+ */
+ window.addEventListener('scroll', debounce(function () {
+ var stuck = { top : undefined, bottom : undefined };
+ var runnerups = { top : undefined, bottom : undefined };
+
+ /*
+ * Recalculate the offsets. Offsets do, for some reason, trigger reflows
+ * of the browser. So, we must read them before making any changes to the
+ * DOM
+ */
+ offset = {x : window.pageXOffset, y : window.pageYOffset };
+
+ /*
+ * Only elements with oncreen contexts are even remotely relevant to this
+ * query, since offscreen contexts never allow their elements to escape.
+ */
+ var onscreen = registered.filter(function (e) {
+ return e.getContext().getElement().getBoundaries().onscreen();
+ });
+
+ /*
+ * Select only the elements to be bound to the top of the page to check
+ * whether the element needs to be pinned
+ */
+ var topbound = onscreen.filter(function(e) {
+ return e.getDirection() === 'top';
+ });
+
+ topbound.sort(function (a, b) {
+ var va = a.getElement().getBoundaries().getScreenOffsetTop();
+ var vb = b.getElement().getBoundaries().getScreenOffsetTop();
+
+ if (va < vb) { return -1; }
+ if (vb < va) { return 1; }
+ return 0;
+ });
+
+ stuck.top = topbound.filter(function(e) { return e.getElement().getBoundaries().getScreenOffsetTop() <= 0;}).pop();
+ runnerups.top = topbound.filter(function(e) { return e.getElement().getBoundaries().getScreenOffsetTop() > 0;}).shift();
+
+ /*
+ * Repeat the same, but do it only with the elements bound to the bottom of
+ * the page.
+ */
+ var bottombound = onscreen.filter(function(e) {
+ return e.getDirection() === 'bottom';
+ });
+
+ bottombound.sort(function (a, b) {
+ var va = a.getElement().getBoundaries().getScreenOffsetBottom();
+ var vb = b.getElement().getBoundaries().getScreenOffsetBottom();
+
+ if (va < vb) { return -1; }
+ if (vb < va) { return 1; }
+ return 0;
+ });
+
+ stuck.bottom = bottombound.filter(function(e) { return e.getElement().getBoundaries().getScreenOffsetBottom() <= 0;}).pop();
+ runnerups.bottom = bottombound.filter(function(e) { return e.getElement().getBoundaries().getScreenOffsetBottom() > 0;}).shift();
+
+ /*
+ * Pin the found elements to the top and / or bottom respectively
+ */
+ pinned.top.setChild(
+ stuck.top && stuck.top.getElement(),
+ stuck.top && stuck.top.getContext().getElement(),
+ runnerups.top && runnerups.top.getElement()
+ );
+
+ pinned.bottom.setChild(
+ stuck.bottom && stuck.bottom.getElement(),
+ stuck.bottom && stuck.bottom.getContext().getElement(),
+ runnerups.bottom && runnerups.bottom.getElement()
+ );
+
+ }), false);
+
+ return {
+ context : findContext,
+
+ stick : function (element, context, direction) {
+ return new Sticky(new Element(wrap(wrap(element))), new Context(new Element(context)), direction);
+ }
+ };
+
+});
\ No newline at end of file
diff --git a/assets/js/ui/dropdown.js b/assets/js/ui/dropdown.js
new file mode 100644
index 0000000..7d7f4da
--- /dev/null
+++ b/assets/js/ui/dropdown.js
@@ -0,0 +1,132 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+depend(function () {
+
+ var listening = [];
+ var onscreen = undefined;
+
+ /**
+ *
+ * @param {type} element
+ * @returns {undefined}
+ */
+ var dropdown = function (element, target) {
+
+ var visible = false;
+ var showing = undefined;
+
+ this.getElement = function () {
+ return element;
+ };
+
+ this.find = function(s) {
+ var e = typeof(element) === 'string'? Array.prototype.slice.call(document.querySelectorAll(element)) : [element];
+ var p = s;
+
+ do {
+ if (e.indexOf(p) !== -1) { return p.getAttribute('data-toggle')? p.getAttribute('data-toggle') : true; }
+ if (p === document.body) { return false; }
+ }
+ while (p = p.parentNode);
+ }
+
+ this.toggle = function (t) {
+ if (!target) {
+ t = document.querySelector('*[data-dropdown="' + t + '"]');
+ }
+ else {
+ t = target;
+ }
+
+ visible = !visible;
+ t.style.display = visible? 'block' : 'none';
+
+ if (visible) {
+ onscreen = this;
+ showing = t;
+ }
+ };
+
+ this.hide = function () {
+ var t;
+
+ if (!target) {
+ t = showing;
+ }
+ else {
+ t = target;
+ }
+
+ if (!t) { return; }
+
+ visible = false;
+ onscreen = null;
+ t.style.display = 'none';
+ };
+
+ this.isShowing = function (el) {
+ do {
+ if (el === showing) { return true; }
+ el = el.parentNode;
+ } while (el !== document.body);
+
+ return false;
+ };
+
+ listening.push(this);
+ this.hide();
+ };
+
+ var listener = function (e) {
+ var found = undefined;
+ var id = undefined;
+
+ for (var i = 0; i < listening.length; i++) {
+ if (id = listening[i].find(e.target)) {
+ found = listening[i];
+ break;
+ }
+ }
+
+ if (found) {
+
+ found.toggle(id);
+
+ e.stopPropagation();
+ e.preventDefault();
+ return;
+ }
+
+ if (onscreen && !onscreen.isShowing(e.target)) {
+ onscreen.hide();
+ }
+
+ };
+
+ document.body.addEventListener('click', listener, false);
+
+ return dropdown;
+});
diff --git a/assets/js/ui/form/styledElements.js b/assets/js/ui/form/styledElements.js
new file mode 100644
index 0000000..ad7bbda
--- /dev/null
+++ b/assets/js/ui/form/styledElements.js
@@ -0,0 +1,16 @@
+
+(function () {
+
+ var checkboxes = document.querySelectorAll('input[type="checkbox"]');
+
+ for (var i = 0; i < checkboxes.length; i++) {
+ var child = document.createElement('span');
+ child.className = 'toggle';
+
+ checkboxes[i].parentNode.insertBefore(child, checkboxes[i].nextSibling);
+ checkboxes[i].classList.add('styled');
+
+ child.addEventListener('click', function (e) { return function () { e.click(); }}(checkboxes[i]), false);
+ }
+
+}());
\ No newline at end of file
diff --git a/assets/scss/_ b/assets/scss/_
new file mode 160000
index 0000000..222139c
--- /dev/null
+++ b/assets/scss/_
@@ -0,0 +1 @@
+Subproject commit 222139cf5331e25b7059dfb4584fe6fac69c5df2
diff --git a/assets/scss/_admin.scss b/assets/scss/_admin.scss
new file mode 100644
index 0000000..7a18113
--- /dev/null
+++ b/assets/scss/_admin.scss
@@ -0,0 +1,20 @@
+
+
+.admin-navigation {
+ background: #222;
+ color: #FFF;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
+
+ .menu-item {
+ background: #222;
+ color: #FFF;
+ padding: 10px;
+ width: 100%;
+ display: inline-block;
+
+ &:hover {
+ background: #FFF;
+ color: #222;
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/scss/_color.scss b/assets/scss/_color.scss
new file mode 100644
index 0000000..b05ff25
--- /dev/null
+++ b/assets/scss/_color.scss
@@ -0,0 +1,48 @@
+/*
+The MIT License
+
+Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Dec 9, 2019, 4:25:00 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+$grey100: #23282C;
+$grey200: #31383D;
+$grey300: #464F56;
+$grey400: #5F6C75;
+$grey500: #74838E;
+$grey600: #8D99A3;
+$grey700: #A9B3B9;
+$grey800: #C1C8CD;
+$grey900: #E6E8EA;
+
+$colors : (
+ "grey-100": $grey100,
+ "grey-200": $grey200,
+ "grey-300": $grey300,
+ "grey-400": $grey400,
+ "grey-500": $grey500,
+ "grey-600": $grey600,
+ "grey-700": $grey700,
+ "grey-800": $grey800,
+ "grey-900": $grey900);
\ No newline at end of file
diff --git a/assets/scss/_dials.scss b/assets/scss/_dials.scss
new file mode 100644
index 0000000..fbb63eb
--- /dev/null
+++ b/assets/scss/_dials.scss
@@ -0,0 +1,93 @@
+
+
+.dials {
+ border-left: solid 1px #CCC;
+ font-size: .8em;
+
+ ul {
+ margin: 2px;
+ padding-left: 10px;
+ list-style-type: none;
+ }
+
+ a {
+ display: inline-block;
+ padding: 2px;
+ text-decoration: none;
+ }
+
+ a:hover {
+ background: #EEE;
+ }
+}
+
+.dial-toggle {
+ @extend .toggle-button;
+ display: block;
+ width: 23px !important;
+ height: 24px;
+ position: absolute;
+ top: 0;
+ right: 0px;
+ display: none;
+ background-color: #FFF;
+ border-radius: 50%;
+ box-shadow: 0 0 2px #CCC;
+}
+
+@media all and (max-width: $MobileBreakpoint) {
+
+ .has-dials {
+ position: relative;
+ }
+
+ .dial-toggle {
+ display: block;
+ }
+
+ .dials {
+ border: solid 1px #CCC;
+ padding: 20px 0;
+ background: #FFF;
+ position: fixed;
+ bottom: 30%;
+ left: 5%;
+ margin: 0 auto;
+ width: 90% !important;
+ display: none;
+ box-shadow: 0 0 3px #CCC;
+ z-index: 10;
+ border-radius: 10px;
+
+ ul {
+ padding: 0;
+ margin: 0;
+ }
+
+ a{
+ display: block;
+ padding: 15px 30px;
+ width: 100%;
+ color: #555;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ }
+
+ .dials-curtain {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ z-index: 9;
+ background: rgba(0, 0, 0, .25);
+
+ transition: .7s opacity 0s ease;
+ opacity: 1;
+
+ &.dnd {
+ opacity: 0;
+ }
+ }
+}
diff --git a/assets/scss/_icon-upload.scss b/assets/scss/_icon-upload.scss
new file mode 100644
index 0000000..38b6c03
--- /dev/null
+++ b/assets/scss/_icon-upload.scss
@@ -0,0 +1,51 @@
+$wrapSize: 128px;
+$loaderSize: 48px;
+$wrapBorderSize: 2px;
+#icon-upload-wrap {
+ position: relative;
+ width: $wrapSize;
+ height: $wrapSize;
+ border: $wrapBorderSize dashed rgba(black, .5);
+ border-radius: 10px;
+ background: url("../img/upload.svg") no-repeat center center;
+ background-size: 64px 64px;
+
+ > input[type="file"] {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: inherit;
+ height: inherit;
+ opacity: 0;
+ }
+
+ &.uploading {
+ background: none;
+
+ &:before {
+ content: '';
+ display: block;
+ width: $loaderSize;
+ height: $loaderSize;
+ margin: ($wrapSize - $loaderSize)/2;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: 50%;
+ border: 6px solid rgba(black, .3);
+ border-left-color: black;
+ box-sizing: border-box;
+ animation: spin .6s linear infinite;
+ }
+ }
+
+ &.uploaded {
+ background: no-repeat center center;
+ background-size: cover;
+ }
+}
+
+@keyframes spin {
+ from { transform: rotate(0deg) }
+ to { transform: rotate(360deg) }
+}
diff --git a/assets/scss/_messages.scss b/assets/scss/_messages.scss
new file mode 100644
index 0000000..2a0da2b
--- /dev/null
+++ b/assets/scss/_messages.scss
@@ -0,0 +1,26 @@
+
+.message {
+ padding: 10px 10px;
+ font-size: 13px;
+ border-color: #777;
+ border-width: 3px;
+ border-style: none none none solid;
+ border-radius: 2px;
+
+ a{
+ font-weight: bold;
+ color: inherit;
+ }
+
+ &.success {
+ border-color: #3C7619;
+ background: #84D950;
+ color: #3C7619;
+ }
+
+ &.error {
+ border-color: #8c1013;
+ background: #F2B5B7;
+ color: #490C0E;
+ }
+}
\ No newline at end of file
diff --git a/assets/scss/_navbar.scss b/assets/scss/_navbar.scss
new file mode 100644
index 0000000..eb21ab9
--- /dev/null
+++ b/assets/scss/_navbar.scss
@@ -0,0 +1,48 @@
+
+$navbar-background: #EEE;
+$navbar-fontColor : #444;
+$navbar-height : 50px;
+$navbar-padding : 15px;
+
+._navbar {
+ background: $navbar-background;
+ box-shadow: 0 2px 2px #DDD;
+ border-bottom: 1px solid #CCC;
+ display: table;
+ width: 100%;
+
+ z-index: 5;
+
+ .left,
+ .right {
+ display: table-cell;
+ padding: $navbar-padding $navbar-padding / 1.5;
+ }
+
+ .right {
+ text-align: right;
+ }
+
+ a {
+ text-decoration: none;
+ color: $navbar-fontColor;
+ font-weight: bold;
+ display: inline-block;
+ padding: 0 $navbar-padding / 1.5;
+ }
+
+ .logo {
+ display: inline-block;
+ float: left;
+ border: none;
+
+ > * {
+ vertical-align: middle;
+ }
+
+ img {
+ height: $navbar-height - 2 * $navbar-padding;
+ margin-right: 5px;
+ }
+ }
+}
diff --git a/assets/scss/_pagination.scss b/assets/scss/_pagination.scss
new file mode 100644
index 0000000..57236b7
--- /dev/null
+++ b/assets/scss/_pagination.scss
@@ -0,0 +1,39 @@
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Apr 17, 2016, 1:23:34 AM
+ Author : cesar
+*/
+
+ul.pagination {
+ list-style: none;
+ text-align: center;
+
+ li {
+ display: inline-block;
+ border: solid 1px #86b8e3;
+ border-left: none;
+ padding: 5px 12px;
+
+ &:first-child {
+ border-left: solid 1px #86b8e3;
+ border-radius: 3px 0 0 3px;
+ }
+
+ &:last-child {
+ border-radius: 0 3px 3px 0;
+ }
+
+ &.disabled, &.disabled a {
+ color: #999;
+ }
+
+ &.current, &.current a {
+ background: #25A9F8;
+ color: #FFF;
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/scss/_properties.scss b/assets/scss/_properties.scss
new file mode 100644
index 0000000..c75733c
--- /dev/null
+++ b/assets/scss/_properties.scss
@@ -0,0 +1,47 @@
+
+.separator {
+ border-top: solid 1px #CCC;
+ margin: 10px 0;
+
+ &.large {
+ margin: 20px 0;
+ }
+
+ &.light {
+ border-top: solid 1px #DDD;
+ }
+}
+
+.editable-property
+{
+
+ display: block;
+
+ > * {
+ vertical-align: top;
+ }
+
+ &.mid-aligned > * {
+ vertical-align: middle;
+ }
+
+ .property-name {
+ display: inline-block;
+ width: 33%;
+ }
+
+ .property-value {
+ display: inline-block;
+ width: 50%;
+
+ }
+
+ .edit-link {
+ display: inline-block;
+ width: 17%;
+
+ .cancel {
+ color: #a00;
+ }
+ }
+}
diff --git a/assets/scss/_vars.scss b/assets/scss/_vars.scss
new file mode 100644
index 0000000..fa751a0
--- /dev/null
+++ b/assets/scss/_vars.scss
@@ -0,0 +1,10 @@
+$LinkColor: #25A9F8;
+
+$MobileBreakpoint: 960px;
+
+%clearfix::after {
+ content: '';
+ display: table;
+ height: 1px;
+ clear: both;
+}
diff --git a/assets/scss/app.scss b/assets/scss/app.scss
new file mode 100644
index 0000000..91add19
--- /dev/null
+++ b/assets/scss/app.scss
@@ -0,0 +1,494 @@
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : 02-jun-2015, 21:46:57
+ Author : cesaradelacalbretschneider
+*/
+
+$disbled-darken-amount: 30;
+
+@import 'reset/_clearfix.scss';
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ font-family: sans-serif;
+ background-color: #FAFAFA;
+}
+
+.hidden {
+ display: none !important;
+}
+
+/*
+ * Disabled items should be unable to receive mouse pointer events. When clicked
+ * or interacted with, these items should be unresponsive.
+ */
+:disabled, .disabled, [disabled] {
+ pointer-events: none;
+}
+
+a {
+ color: #555;
+ text-decoration: none;
+
+ &:hover {
+ color: #333;
+ }
+
+ &.highlighted {
+ color: #2a912e;
+
+ &:hover {
+ color: #2a912e;
+ }
+ }
+
+ &.heavy {
+ font-weight: bold;
+ }
+
+ img {
+ border: none;
+ }
+}
+
+
+h1 {
+ font-size: 20px;
+ color: #2a912e;
+ font-weight: normal;
+ background: #FAFAFA;
+
+ &.unpadded {
+ margin: 0;
+ padding: 0;
+ }
+}
+
+h2 {
+ color: #353535;
+ font-size: 18px;
+}
+
+p {
+ color: #555;
+ line-height: 1.6em;
+
+ &.unpadded {
+ margin: 0;
+ }
+
+ &.small {
+ font-size: .78em;
+ }
+
+ &.secondary {
+ color: #777;
+
+ a {
+ color: #333;
+ }
+ }
+}
+
+blockquote {
+ margin-left : 0;
+ padding: 15px 5px 15px 15px;
+ border-left : solid 3px #AAA;
+ background: #F9F9F9;
+ color: #555;
+ font-size: .9em;
+}
+
+table {
+ width: 100%;
+ border-radius: 3px;
+ border-collapse: collapse;
+ font-size: .85em;
+
+ thead tr {
+ box-shadow: 1px 1px 2px #CCC;
+
+ th {
+ border-bottom: solid 1px #AAA;
+ background: #888;
+ color: #FFF;
+
+ &:first-child {
+ border-radius: 2px 0px 0 0;
+ }
+
+ &:last-child {
+ border-radius: 0px 2px 0 0;
+ }
+ }
+ }
+
+ tr {
+ background: #FFF;
+ border-top: solid 1px #EEE;
+ }
+
+ tr:first-child {
+ border-top: none;
+ }
+
+ tr:nth-child(2n) {
+ background: #FAFAFA;
+ }
+
+ td, th {
+ margin: 0;
+ padding: 8px 20px;
+ }
+}
+
+form.regular {
+
+ .field {
+ display: block;
+ box-sizing: border-box;
+
+
+ label {
+ display: block;
+ font-size: .9em;
+ color: #555;
+ width: 100%;
+ }
+
+ input[type=text],
+ input[type=email],
+ input[type=password],
+ textarea,
+ select {
+ width: 100%;
+ padding: 5px 10px;
+ font-size: 1.05em;
+ background: #FFF;
+ border: solid 1px #EEE;
+ box-sizing: border-box;
+ height: 2em;
+
+ &.borderless {
+ border: none;
+ }
+
+ &:focus {
+ outline: none;
+ }
+ }
+
+ textarea {
+ height: 150px;
+ }
+ }
+
+ .form-footer {
+ padding-top: 15px;
+ padding-right: 10px;
+ margin-top: 15px;
+ text-align: right;
+
+ * {
+ vertical-align: middle;
+ }
+
+ a {
+ font-size: .8em;
+ }
+ }
+
+ input[type="submit"] {
+ @extend .button;
+ margin-left: 15px;
+ font-family: sans-serif;
+ }
+}
+
+.material-form {
+ input[type="text"], .fake-field, .fake-field-ph {
+ display: inline-block;
+ padding: 3px 6px;
+ max-width: 95%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ .fake-field-ph {
+ border: 1px solid transparent;
+ }
+ input[type="text"], .fake-field {
+ border: 1px solid grey;
+ background: #fff;
+ font-size: 16px;
+ font-family: inherit;
+ vertical-align: baseline;
+ }
+ .fake-field {
+ user-select: all;
+ }
+}
+
+.no-selection {
+ user-select: none;
+}
+
+.button {
+ $bg: #3191f1;
+ $boxshadow: #3167f1;
+ background: $bg;
+ box-shadow: -2px -2px 1px $boxshadow inset;
+
+ border: none;
+ border-radius: 3px;
+ color: #ffffff;
+ font-weight: bold;
+ padding: .7em 1.2em;
+ cursor: pointer;
+ text-decoration: none;
+ display: inline-block;
+
+ &:disabled {
+ background-color: darken($bg, $disbled-darken-amount);
+ box-shadow: -2px -2px 1px darken($boxshadow, $disbled-darken-amount) inset;
+ cursor: not-allowed;
+ }
+
+ &.error {
+ background: adjust_hue($bg, 150);
+ box-shadow: -2px -2px 1px darken(adjust_hue($boxshadow, 160), 30) inset;
+ }
+
+ &.success {
+ background: darken(adjust_hue($bg, -80), 20);
+ box-shadow: -2px -2px 1px darken(adjust_hue($boxshadow, -90), 40) inset;
+ }
+
+ &.small {
+ padding: .35em .5em;
+ font-size: .78em;
+ }
+
+ &.secondary {
+ color: #777;
+ }
+
+ &:hover {
+ color: #FFF;
+ }
+}
+
+.menubar {
+ background: #FEFEFE;
+ vertical-align: top;
+ text-align: right;
+ box-shadow: 0 2px 2px #DDD;
+ border-bottom: solid 1px #CCC;
+
+ z-index: 5;
+
+ a {
+ display: inline-block;
+ text-decoration: none;
+ color: #333;
+ padding: 10px 15px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ }
+
+ a:hover {
+ text-shadow: 0 0 4px #DDD;
+ }
+
+ .logo {
+ display: inline-block;
+ float: left;
+ border: none;
+ }
+}
+
+.badge {
+ width: 100%;
+ padding: .5em;
+ box-shadow: -2px 2px 2px #EAEAEA inset;
+ background: #FAFAFA;
+ border: solid 1px #CCC;
+ display: block;
+ border-radius: 3px;
+}
+
+footer {
+ background: #FFF;
+ color: #555;
+ text-align: center;
+ padding: 5px;
+ line-height: 20px;
+ font-size: 12px;
+ border-top: solid 1px #CCC;
+}
+
+.material {
+ background: #FFF;
+ box-shadow: 1px 1px 1px #DDD;
+ border-radius: 2px;
+ border: solid 1px #CCC;
+ padding: 20px 15px 15px;
+
+ &.unpadded {
+ padding: 0;
+ }
+
+ .padded {
+ padding: 20px 15px 15px;
+ }
+
+ .inset {
+ color: #FFF;
+ background: #888;
+ box-shadow: inset 1px 1px 2px #666;
+
+ p, a {
+ color: #FFF;
+ }
+
+ &:last-child {
+ border-radius: 0 0 2px 2px;
+ }
+ }
+}
+
+.login-logo {
+ text-align: center;
+
+ img {
+ max-width: 500px;
+ }
+}
+
+%icon-sizing {
+
+ &.extra-small {
+ width: 24px;
+ height: 24px;
+ }
+
+ &.small {
+ width: 32px;
+ height: 32px;
+ }
+
+ &.medium {
+ width: 64px;
+ height: 64px;
+ }
+
+ &.big {
+ width: 128px;
+ height: 128px;
+ }
+
+ &.huge {
+ width: 256px;
+ height: 256px;
+ }
+
+ &.full-width {
+ max-width: 100%;
+ }
+}
+
+.user-name {
+ vertical-align: middle;
+ display: inline-block;
+ font-size: 1.2em;
+ color: #333;
+ text-decoration: none;
+}
+
+.user-icon {
+ border-radius: 50%;
+ display: inline-block;
+ vertical-align: middle;
+ border: solid 2px #FFF;
+
+ @extend %icon-sizing;
+
+ &.square {
+ border-radius: 10px;
+ }
+}
+
+.app-name {
+ vertical-align: middle;
+ display: inline-block;
+ font-size: 1em;
+ color: #333;
+ text-decoration: none;
+}
+
+.app-icon {
+ border-radius: 3px;
+ border-radius: 3px;
+ box-shadow: 0 0 2px #CCC;
+ vertical-align: middle;
+
+ @extend %icon-sizing;
+
+ &+.app-name {
+ margin-left: .4em;
+ }
+}
+
+.validation-errors
+{
+ color: #900;
+ list-style: none;
+ font-size: .9em;
+ margin: 10px 0;
+ padding: 0;
+
+ li {
+ border-left: solid 2px #900;
+ padding-left: 10px;
+ margin-top: 8px;
+ }
+
+ .error-message {
+ font-weight: bold;
+ display: block;
+ }
+
+ .extended-message {
+ font-size: .9em;
+ }
+}
+
+.heading {
+ display: block;
+ padding: 10px 5px;
+ color: #FFF;
+ font-weight: bold;
+ color: #2a912e;
+ border-bottom: solid 1px #2a912e;
+ background: #FAFAFA;
+}
+
+
+@import '_vars.scss';
+@import '_color.scss';
+@import '_/_.scss';
+@import 'ui/_ui.scss';
+@import '_navbar';
+@import '_admin.scss';
+@import '_pagination';
+@import '_properties';
+@import '_messages';
+@import '_icon-upload';
+@import '_dials';
diff --git a/assets/scss/drawer.scss b/assets/scss/drawer.scss
new file mode 100644
index 0000000..c3efc63
--- /dev/null
+++ b/assets/scss/drawer.scss
@@ -0,0 +1,2 @@
+
+@import "ui/_app-switcher.scss";
\ No newline at end of file
diff --git a/assets/scss/reset/_clearfix.scss b/assets/scss/reset/_clearfix.scss
new file mode 100644
index 0000000..a643eb8
--- /dev/null
+++ b/assets/scss/reset/_clearfix.scss
@@ -0,0 +1,8 @@
+
+
+%clearfix::after {
+ content: '';
+ display: table;
+ height: 1px;
+ clear: both;
+}
\ No newline at end of file
diff --git a/assets/scss/ui/_app-switcher.scss b/assets/scss/ui/_app-switcher.scss
new file mode 100644
index 0000000..b9d440b
--- /dev/null
+++ b/assets/scss/ui/_app-switcher.scss
@@ -0,0 +1,123 @@
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : 21.03.2018, 14:52:40
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+$app-switcher-fg-color : #777;
+$app-switcher-bg-color : #EAEAEA;
+$app-switcher-tile-size : 5px;
+
+.app-switcher.toggle {
+ vertical-align: middle;
+ background-color: $app-switcher-fg-color;
+ display: inline-block;
+ width: $app-switcher-tile-size * 4;
+ height: $app-switcher-tile-size * 4;
+ cursor: pointer;
+
+ background-image:
+ linear-gradient(
+ 0deg,
+ transparent $app-switcher-tile-size * 0, transparent $app-switcher-tile-size * 1,
+ $app-switcher-bg-color $app-switcher-tile-size * 1, $app-switcher-bg-color $app-switcher-tile-size * 1.5,
+ transparent $app-switcher-tile-size * 1.5, transparent $app-switcher-tile-size * 2.5,
+ $app-switcher-bg-color $app-switcher-tile-size * 2.5, $app-switcher-bg-color $app-switcher-tile-size * 3,
+ transparent $app-switcher-tile-size * 3, transparent $app-switcher-tile-size * 4
+ ),
+
+ linear-gradient(
+ 90deg,
+ transparent $app-switcher-tile-size * 0, transparent $app-switcher-tile-size * 1,
+ $app-switcher-bg-color $app-switcher-tile-size * 1, $app-switcher-bg-color $app-switcher-tile-size * 1.5,
+ transparent $app-switcher-tile-size * 1.5, transparent $app-switcher-tile-size * 2.5,
+ $app-switcher-bg-color $app-switcher-tile-size * 2.5, $app-switcher-bg-color $app-switcher-tile-size * 3,
+ transparent $app-switcher-tile-size * 3, transparent $app-switcher-tile-size * 4
+ )
+
+ ;
+}
+
+.app-drawer
+{
+
+ text-align: left;
+
+ .app-entry {
+ padding: 10px 12px;
+ border-radius: 2px;
+ border: solid 1px transparent;
+ background-color: transparent;
+ display: inline-block;
+ width: 100%;
+ text-align: center;
+ text-decoration: none;
+
+ transition: border .1s ease-in, background-color .1s ease-in;
+
+ &:hover {
+ background-color: #F9F9F9;
+ border: solid 1px #CCC;
+ }
+ }
+
+ .app-icon-drawer {
+ margin: 0 auto;
+ width: 90%;
+ height: auto;
+ display: block;
+ }
+
+ .app-name-drawer {
+ text-align: center;
+ display: block;
+ font-size: .75em;
+ color: #242424;
+ margin-top: .75em;
+ margin-bottom: .25em;
+ width: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-weight: normal;
+ }
+
+ .footer {
+ background: #EEE;
+ text-align: center;
+ display: block;
+ padding: 10px 15px;
+ color: #888;
+ font-weight: bold;
+ font-size: .8em;
+
+ background-image: linear-gradient(180deg, #CCC 0px, transparent 3px);
+
+ &:hover {
+ color: #777;
+ background-color: #D5D5D5;
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/scss/ui/_dropdown.scss b/assets/scss/ui/_dropdown.scss
new file mode 100644
index 0000000..bb3743f
--- /dev/null
+++ b/assets/scss/ui/_dropdown.scss
@@ -0,0 +1,87 @@
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : 21.03.2018, 15:18:50
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+$dropdown-border-color: #DDD;
+
+.has-dropdown {
+ position: relative;
+}
+
+.dropdown {
+ display: none;
+ position: absolute;
+ top: 100%;
+ left: -20px;
+ width: 100%;
+ min-width: 300px;
+ max-width: 100%;
+ margin-top: 20px;
+ background: #FFF;
+ border: solid 1px $dropdown-border-color;
+ border-radius: 3px;
+ padding: 5px;
+ z-index: 99999999999;
+ padding: 10px;
+ box-shadow: 0 0 7px rgba(0, 0, 0, 0.2);
+
+ &:before,
+ &:after {
+ content: '';
+ height: 10px;
+ width: 10px;
+ display: block;
+ position: absolute;
+ bottom: 100%;
+ }
+
+ &:before {
+ left: 20px;
+ background-image: linear-gradient(-225deg, transparent 7px, $dropdown-border-color 7px, $dropdown-border-color 8px, #FFF 9px);
+ }
+
+ &:after {
+ left: 30px;
+ background-image: linear-gradient(+225deg, transparent 7px, $dropdown-border-color 7px, $dropdown-border-color 8px, #FFF 9px);
+ }
+
+ &.right-bound {
+ right: -20px;
+ left: auto;
+
+ &:before { left: auto; right: 30px; }
+ &:after { left: auto; right: 20px; }
+ }
+
+ &.unpadded {
+ padding: 0;
+ }
+
+ .padded {
+ padding: 5px;
+ }
+}
\ No newline at end of file
diff --git a/assets/scss/ui/_ui.scss b/assets/scss/ui/_ui.scss
new file mode 100644
index 0000000..a579af4
--- /dev/null
+++ b/assets/scss/ui/_ui.scss
@@ -0,0 +1,13 @@
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Oct 10, 2017, 11:59:43 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+@import "_dropdown.scss";
+@import "form/_form.scss";
+@import "layout/__layout.scss";
\ No newline at end of file
diff --git a/assets/scss/ui/form/_checkbox.scss b/assets/scss/ui/form/_checkbox.scss
new file mode 100644
index 0000000..cf63b82
--- /dev/null
+++ b/assets/scss/ui/form/_checkbox.scss
@@ -0,0 +1,49 @@
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Oct 10, 2017, 11:58:05 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+input[type=checkbox].styled {
+ display: none;
+
+ + span.toggle {
+ display: inline-block;
+ position: relative;
+ width: 1.5em;
+ height: .5em;
+ background-color: #DDD;
+ border-radius: 5px;
+ vertical-align: .11em;
+ margin: 0 .4em;
+
+ transition: background-color .3s linear;
+
+ &:before {
+ display: block;
+ position: absolute;
+ top: -.20em;
+ left: 0;
+ height: .85em;
+ width: .9em;
+ border-radius: 50%;
+ background: #FFF;
+ border: solid 1px #777;
+ content: '';
+
+ transition: left .3s ease;
+ }
+ }
+
+ &:checked + span.toggle {
+ background-color: #a1d49d;
+
+ &:before {
+ left: 50%;
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/scss/ui/form/_condensed.scss b/assets/scss/ui/form/_condensed.scss
new file mode 100644
index 0000000..c0bf771
--- /dev/null
+++ b/assets/scss/ui/form/_condensed.scss
@@ -0,0 +1,208 @@
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 6, 2018, 5:21:03 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+
+form.condensed {
+ margin: 0 auto;
+
+ .field {
+ margin: 0;
+ }
+
+ label {
+ display: none;
+ }
+
+ input,
+ textarea {
+ /*
+ * These remove the annoyng styles from the iOS layout that will style
+ * input for you.
+ */
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ }
+
+ input[type="email"],
+ input[type="password"],
+ input[type="text"],
+ textarea {
+ border : none;
+ border-top : none;
+ border-bottom : none;
+ border-radius: 0;
+
+ margin: 0;
+ font-size: 17px;
+ width: 100%;
+ padding: 10px;
+
+ box-sizing: border-box;
+
+ /*Make the splitter lines. We don't use border to avoid them invading the border */
+ background-image: linear-gradient(180deg, #DDD 1px, #FFF 1px);
+
+ }
+
+ /*
+ * Textareas do have specific styles, including smaller text to make them more
+ * useful for users typing in bigger segments of text
+ */
+ textarea {
+ font-size: .9em;
+ height: 8em;
+ }
+
+ .field:first-child input[type="email"],
+ .field:first-child input[type="text"],
+ .field:first-child input[type="password"],
+ .field:first-child textarea {
+ border-top : solid 1px #999;
+ background-image: linear-gradient(180deg, #ccc 0%, #fff 8%);
+ }
+
+ input[type="submit"] {
+ border : solid 1px #529EBB;
+ border-top : none;
+ font-family: sans-serif;
+
+ $bg: #25A9F8;
+ $color: #FFF;
+ background-color: $bg;
+ color: $color;
+ margin: 0;
+ font-size: 20px;
+ width: 100%;
+ padding: 10px;
+ cursor: pointer;
+
+ box-sizing: border-box;
+
+ background-image: linear-gradient(0deg, #0571B1 0%, $bg 6%);
+
+
+ &:disabled {
+ color: darken($color, $disbled-darken-amount);
+ background: darken($bg, $disbled-darken-amount) !important;
+ cursor: not-allowed;
+ }
+ }
+
+ .message {
+ position: relative;
+ padding: 10px 10px;
+ font-size: 13px;
+ border-width: 0 1px;
+ border-style: solid;
+
+ &.success {
+ border-color: #3C7619;
+ background: #84D950;
+ color: #3C7619;
+
+ &:after {
+ border-color: transparent transparent #84D950 transparent;
+ }
+ }
+
+ &.info {
+ border-color: #CCC;
+ background: #EEE;
+ color: #555;
+
+ &:after {
+ border-color: transparent transparent #EEE transparent;
+ }
+ }
+
+ &.error {
+ border-color: #590C0E;
+ background: #F2B5B7;
+ color: #490C0E;
+
+ &:after {
+ border-color: transparent transparent #F2B5B7 transparent;
+ }
+ }
+
+ &:after {
+ position: absolute;
+ bottom: 100%;
+ right: 20px;
+ display: block;
+ width: 0;
+ height: 0;
+ content: '';
+
+ border-style: none solid solid solid;
+ border-color: transparent transparent #CCC transparent;
+ border-width: 7px;
+ }
+ }
+
+ .description {
+ background: #FFF;
+ padding: 10px;
+ color: #333;
+ font-size: 13px;
+ }
+
+ &.standalone {
+ max-width: 350px;
+ border-radius: 4px;
+ overflow: hidden;
+ box-shadow: 0 0 5px rgba(0, 0, 0, .7);
+
+ input:first-child,
+ input:last-child {
+ background-image: none;
+ border-top: none;
+ }
+
+ input[type="submit"] {
+
+ transition: background-color .5s ease, background-size .5s ease;
+ background-size : 0 0;
+ background-repeat: no-repeat;
+ background-position: 50% 50%;
+
+ &:hover {
+ background-color: #1599E8;
+ }
+
+ &:active {
+ background-color: #35B9F8;
+ }
+ }
+
+ .message {
+ border-left: none;
+ border-right: none;
+ }
+ }
+}
diff --git a/assets/scss/ui/form/_form.scss b/assets/scss/ui/form/_form.scss
new file mode 100644
index 0000000..d0f1a59
--- /dev/null
+++ b/assets/scss/ui/form/_form.scss
@@ -0,0 +1,12 @@
+/*
+To change this license header, choose License Headers in Project Properties.
+To change this template file, choose Tools | Templates
+and open the template in the editor.
+*/
+/*
+ Created on : Oct 10, 2017, 11:59:49 AM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+@import "_checkbox.scss";
+@import "_condensed.scss";
\ No newline at end of file
diff --git a/assets/scss/ui/layout/__layout.scss b/assets/scss/ui/layout/__layout.scss
new file mode 100644
index 0000000..5960233
--- /dev/null
+++ b/assets/scss/ui/layout/__layout.scss
@@ -0,0 +1,29 @@
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 7, 2018, 2:39:55 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+@import '_toggle.scss';
diff --git a/assets/scss/ui/layout/_toggle.scss b/assets/scss/ui/layout/_toggle.scss
new file mode 100644
index 0000000..8c40ffc
--- /dev/null
+++ b/assets/scss/ui/layout/_toggle.scss
@@ -0,0 +1,65 @@
+/*
+The MIT License
+
+Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+/*
+ Created on : Jun 7, 2018, 2:39:33 PM
+ Author : César de la Cal Bretschneider <cesar@magic3w.com>
+*/
+
+.toggle-button {
+ display: inline-block;
+ position: relative;
+ vertical-align: middle;
+ width : 38px;
+ height: 17px;
+ padding: 0px;
+ background-image: linear-gradient(180deg, #FFF 3px, transparent 3px, transparent 7px, #FFF 7px, #FFF 10px, transparent 10px, transparent 14px, #FFF 14px);
+ background-size: 20px 17px;
+ background-position: center center;
+ background-repeat: no-repeat;
+
+ &.hidden {
+ display: none;
+ }
+
+ &.medium {
+ background-image: linear-gradient(180deg, #777 3px, transparent 3px, transparent 7px, #777 7px, #777 10px, transparent 10px, transparent 14px, #777 14px);
+
+ &:after, &:before {
+ background: #242424;
+ }
+ }
+
+ &.dark {
+ background-image: linear-gradient(180deg, #242424 3px, transparent 3px, transparent 7px, #242424 7px, #242424 10px, transparent 10px, transparent 14px, #242424 14px);
+
+ &:after, &:before {
+ background: #242424;
+ }
+ }
+
+ &.narrow {
+ background-size: 3px 17px;
+ width: 20px;
+ }
+}
diff --git a/bin/classes/BaseController.php b/bin/classes/BaseController.php
new file mode 100644
index 0000000..8acb431
--- /dev/null
+++ b/bin/classes/BaseController.php
@@ -0,0 +1,73 @@
+<?php
+
+use auth\SSO;
+use auth\SSOCache;
+use auth\Token;
+use spitfire\cache\MemcachedAdapter;
+use spitfire\core\Environment;
+use spitfire\io\session\Session;
+
+abstract class BaseController extends Controller
+{
+
+ /**
+ *
+ * @var SSO
+ */
+ public $sso;
+
+ /**
+ *
+ * @var \hook\Hook
+ */
+ public $hook;
+
+ protected $user;
+
+ /**
+ *
+ * @var \auth\AppAuthentication
+ */
+ protected $authapp;
+
+
+ protected $core;
+
+ /**
+ *
+ * @var Token
+ */
+ protected $token;
+
+
+ public function _onload() {
+ $session = Session::getInstance();
+
+ #Create a brief cache for the sessions.
+ $cache = new MemcachedAdapter();
+ $cache->setTimeout(120);
+
+ #Create a user
+ $this->sso = new SSOCache(Environment::get('SSO'));
+ $this->token = isset($_GET['token'])? $this->sso->makeToken($_GET['token']) : $session->getUser();
+
+ #Check if hook is enabled and start it
+ $this->hook = Environment::get('hook.url') ? new \hook\Hook(Environment::get('hook.url'), $this->sso->makeSignature(Environment::get('hook.id'))) : null;
+
+ #Fetch the user from the cache if necessary
+ $this->user = $this->token && $this->token instanceof Token? $cache->get('relay_token_' . $this->token->getId(), function () {
+ return $this->token->isAuthenticated()? $this->token->getTokenInfo()->user : null;
+ }) : null;
+
+ $this->authapp = isset($_GET['signature'])? $this->sso->authApp($_GET['signature']) :
+ ($this->user? $cache->get('relay_token_app_' . $this->token->getId(), function () {
+ return $this->token->getTokenInfo()->app->id;
+ }) : null);
+
+ #Maintain the user in the view. This way we can draw an interface for them
+ $this->view->set('authUser', $this->user);
+ $this->view->set('sso', $this->sso);
+
+ }
+
+}
diff --git a/bin/classes/IP.php b/bin/classes/IP.php
new file mode 100644
index 0000000..a26e5a6
--- /dev/null
+++ b/bin/classes/IP.php
@@ -0,0 +1,42 @@
+<?php
+
+use spitfire\cache\MemcachedAdapter;
+
+class IP
+{
+ /**
+ * This is awful. And I wish I wasn't making this kind of compromise.
+ */
+ public static function makeLocation() {
+ $ip = isset($_SERVER['HTTP_X_FORWARDED_FOR'])? $_SERVER['HTTP_X_FORWARDED_FOR']: $_SERVER['REMOTE_ADDR'];
+
+ /*
+ * Prepare the memcached adapter so we don't force the API.
+ */
+ $m = new MemcachedAdapter();
+ $m->setTimeout(86400 * 30);
+
+ return $m->get('ip_' . $ip, function() use ($ip) {
+ /*
+ * Extract the IP from the request
+ */
+ $r = file_get_contents(sprintf('http://api.ipstack.com/%s?access_key=%s', $ip, \spitfire\core\Environment::get('ipstack.key')));
+
+ /*
+ * Check if the request returned anything
+ */
+ if (!$r) { return false; }
+ if (!strstr($http_response_header[0], '200')) { return false; }
+
+ /*
+ * If everything went well with the request. We check the response and
+ * decode it with JSON
+ */
+ $data = json_decode($r);
+
+ return $data;
+ });
+ }
+
+}
+
diff --git a/bin/error_pages/spitfire/exceptions/PublicException/404.json.php b/bin/classes/auth/App.php
similarity index 61%
copy from bin/error_pages/spitfire/exceptions/PublicException/404.json.php
copy to bin/classes/auth/App.php
index 4908905..0c9868c 100644
--- a/bin/error_pages/spitfire/exceptions/PublicException/404.json.php
+++ b/bin/classes/auth/App.php
@@ -1,27 +1,69 @@
-<?php
+<?php namespace auth;
/*
* The MIT License
*
- * Copyright 2020 César de la Cal Bretschneider <cesar@magic3w.com>.
+ * Copyright 2017 César de la Cal Bretschneider <cesar@magic3w.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-echo json_encode(['error' => 'Not found']);
\ No newline at end of file
+class App
+{
+
+ private $id;
+
+ private $secret;
+
+ private $name;
+
+ public function __construct($id, $secret, $name) {
+ $this->id = $id;
+ $this->secret = $secret;
+ $this->name = $name;
+ }
+
+ public function getId() {
+ return $this->id;
+ }
+
+ public function getSecret() {
+ return $this->secret;
+ }
+
+ public function getName() {
+ return $this->name;
+ }
+
+ public function setId($id) {
+ $this->id = $id;
+ return $this;
+ }
+
+ public function setSecret($secret) {
+ $this->secret = $secret;
+ return $this;
+ }
+
+ public function setName($name) {
+ $this->name = $name;
+ return $this;
+ }
+
+}
diff --git a/bin/classes/auth/AppAuthentication.php b/bin/classes/auth/AppAuthentication.php
new file mode 100644
index 0000000..9d7b68c
--- /dev/null
+++ b/bin/classes/auth/AppAuthentication.php
@@ -0,0 +1,117 @@
+<?php namespace auth;
+
+/*
+ * The MIT License
+ *
+ * Copyright 2017 César de la Cal Bretschneider <cesar@magic3w.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+class AppAuthentication
+{
+
+ /**
+ *
+ * @var SSO
+ */
+ private $sso;
+ private $local;
+ private $remote;
+
+ /**
+ *
+ * @var Context[]
+ */
+ private $contexts;
+ private $token;
+
+ public function __construct($sso, $src, $remote, $context, $token) {
+ $this->sso = $sso;
+ $this->local = $src;
+ $this->remote = $remote;
+ $this->contexts = $context;
+ $this->token = $token;
+ }
+
+ /**
+ *
+ * @deprecated since version 20180704
+ * @return boolean
+ */
+ public function getAuthenticated() {
+ return true;
+ }
+
+ public function getRemote() {
+ return $this->remote;
+ }
+
+ /**
+ *
+ * @return Context
+ */
+ public function getContext($name) {
+ return $this->contexts[$name];
+ }
+
+ public function getRedirect($tgt, $contexts = null) {
+ if ($contexts === null) {
+ $contexts = [];
+ }
+
+ foreach ($contexts as $ctx) {
+ $signatures[] = (string)$this->sso->makeSignature($tgt, [$ctx instanceof Context? $ctx->getId() : $ctx]);
+ }
+
+ return $this->sso->getEndpoint() . '/auth/connect?' . http_build_query(['signature' => $signatures]);
+ }
+
+ public function setRemote($remote) {
+ $this->remote = $remote;
+ return $this;
+ }
+
+ public function setContext($context) {
+ $this->contexts = $context;
+ return $this;
+ }
+
+ public function setToken($token) {
+ $this->token = $token;
+ return $this;
+ }
+
+ /**
+ *
+ * @return App
+ */
+ public function getSrc() {
+ return $this->local;
+ }
+
+ public function getToken() {
+ return $this->token;
+ }
+
+ public function setSrc($src) {
+ $this->local = $src;
+ return $this;
+ }
+}
diff --git a/bin/classes/auth/Context.php b/bin/classes/auth/Context.php
new file mode 100644
index 0000000..f746f50
--- /dev/null
+++ b/bin/classes/auth/Context.php
@@ -0,0 +1,99 @@
+<?php namespace auth;
+
+/*
+ * The MIT License
+ *
+ * Copyright 2017 César de la Cal Bretschneider <cesar@magic3w.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+class Context
+{
+
+ private $sso;
+ private $app;
+ private $id;
+ private $exists = null;
+ private $granted = null;
+
+ /**
+ *
+ * @param SSO $sso
+ * @param App $app
+ * @param string $id
+ */
+ public function __construct($sso, $app, $id) {
+ $this->sso = $sso;
+ $this->app = $app;
+ $this->id = $id;
+ }
+
+ public function getApp() {
+ return $this->app;
+ }
+
+ public function getId() {
+ return $this->id;
+ }
+
+ public function exists() {
+ return $this->exists;
+ }
+
+ public function setApp($app) {
+ $this->app = $app;
+ return $this;
+ }
+
+ public function setId($name) {
+ $this->id = $name;
+ return $this;
+ }
+
+ public function setExists($exists) {
+ $this->exists = $exists;
+ return $this;
+ }
+
+ public function setGranted($granted) {
+ $this->granted = $granted;
+ }
+
+ public function isGranted() {
+ return ((int)$this->granted) === 2;
+ }
+
+ public function isDenied() {
+ return ((int)$this->granted) === 1;
+ }
+
+ public function create($name, $description) {
+ $request = new Request(
+ $this->sso->getEndpoint() . '/context/create.json',
+ ['context' => $this->id, 'signature' => (string)$this->sso->makeSignature()]
+ );
+
+ $request->send(['name' => $name, 'description' => $description]);
+
+ $this->exists = true;
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/bin/classes/auth/File.php b/bin/classes/auth/File.php
new file mode 100644
index 0000000..99b3faf
--- /dev/null
+++ b/bin/classes/auth/File.php
@@ -0,0 +1,20 @@
+<?php namespace auth;
+
+class File
+{
+
+ private $previewURL;
+ private $downloadURL;
+
+ public function __construct($previewURL, $downloadURL) {
+ $this->previewURL = $previewURL;
+ $this->downloadURL = $downloadURL;
+ }
+
+ public function getPreviewURL($w = null, $h = null) {
+ list($url, $qstring) = explode('?', $this->previewURL, 2);
+ return implode('/', Array(trim($url, '/'), $w, $h)) . '/?' . $qstring;
+ }
+
+
+}
\ No newline at end of file
diff --git a/bin/error_pages/spitfire/exceptions/PublicException/404.json.php b/bin/classes/auth/JSON.php
similarity index 74%
copy from bin/error_pages/spitfire/exceptions/PublicException/404.json.php
copy to bin/classes/auth/JSON.php
index 4908905..addc011 100644
--- a/bin/error_pages/spitfire/exceptions/PublicException/404.json.php
+++ b/bin/classes/auth/JSON.php
@@ -1,27 +1,42 @@
-<?php
+<?php namespace auth;
+
+use spitfire\exceptions\PrivateException;
/*
* The MIT License
*
- * Copyright 2020 César de la Cal Bretschneider <cesar@magic3w.com>.
+ * Copyright 2018 César de la Cal Bretschneider <cesar@magic3w.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-echo json_encode(['error' => 'Not found']);
\ No newline at end of file
+class JSON
+{
+
+ public static function decode($string) {
+
+ $data = json_decode($string);
+
+ if (json_last_error() !== JSON_ERROR_NONE) {
+ throw new PrivateException('Invalid JSON - ' . json_last_error_msg(), 1806251459);
+ }
+
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/bin/classes/auth/Request.php b/bin/classes/auth/Request.php
new file mode 100644
index 0000000..24032d6
--- /dev/null
+++ b/bin/classes/auth/Request.php
@@ -0,0 +1,92 @@
+<?php namespace auth;
+
+use Exception;
+
+/**
+ * The request class is in charge of properly establishing HTTP connections with
+ * the remote server, retrieving the data and returning it or an error in the
+ * event of it failing.
+ *
+ * @author César de la Cal Bretschneider <cesar@magic3w.com>
+ */
+class Request
+{
+
+ private $url;
+
+ /**
+ * Parameters are handled separately from the URL just because they can happen
+ * to be a pain and are way more comfy to handle in array form.
+ *
+ * @var string[]
+ */
+ private $parameters;
+
+ /**
+ * Depending on whether this array contains data we will be sending a POST or
+ * a GET request. Also, if it contains data this will be the post payload.
+ *
+ * @var mixed[]|null
+ */
+ private $postData;
+
+ /**
+ *
+ * @param string $url
+ * @param string[] $parameters
+ */
+ public function __construct($url, $parameters = Array()) {
+ $this->url = $url;
+ $this->parameters = $parameters;
+ }
+
+ /**
+ * This contains the data that will be posted to the server when the request
+ * is sent. This can be overriden by passing a parameter to the send method.
+ *
+ * @param string[] $data
+ */
+ public function setPostData($data) {
+ $this->postData = $data;
+ }
+
+ /**
+ *
+ * @param string[] $data MAy contain postdata
+ *
+ * @return mixed
+ */
+ public function send($data = null) {
+ #Find the appropriate data
+ if (!$data) { $data = $this->postData; }
+
+ #Assemble the full URI
+ $url = $this->url;
+ if (!empty($this->parameters)) { $url.= '?' . http_build_query($this->parameters); }
+
+ #Prepare the cURL request
+ $ch = curl_init($url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+
+ #If data is there to be posted we will send that
+ if (!empty($data)) {
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
+ }
+
+ #Get the cURL response
+ $response = curl_exec($ch);
+
+ #If the request was not okay we will return an error
+ $http_response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+
+ if ($http_response_code !== 200) {
+ throw new Exception('SSO rejected the request (' . curl_error($ch) . ')', 1605141533);
+ }
+
+ #Return the response we received
+ return $response;
+ }
+
+
+}
diff --git a/bin/classes/auth/SSO.php b/bin/classes/auth/SSO.php
new file mode 100644
index 0000000..d52247e
--- /dev/null
+++ b/bin/classes/auth/SSO.php
@@ -0,0 +1,209 @@
+<?php namespace auth;
+
+use Exception;
+use signature\Hash;
+use signature\Signature;
+
+class SSO
+{
+
+ private $endpoint;
+ private $appId;
+ private $appSecret;
+
+ public function __construct($credentials) {
+ $reflection = URLReflection::fromURL($credentials);
+
+ $this->endpoint = rtrim($reflection->getProtocol() . '://' . $reflection->getServer() . ':' . $reflection->getPort() . $reflection->getPath(), '/');
+ $this->appId = $reflection->getUser();
+ $this->appSecret = $reflection->getPassword();
+
+ if (!$this->appSecret) {
+ throw new Exception('App Secret is missing', 1807021658);
+ }
+ }
+
+ /**
+ * Creates a new SSO Token. This allows your application to request a single
+ * user's token and manage it.
+ */
+ public function createToken($expires = null) {
+ /*
+ * Fetch the JSON message from the endpoint. This should tell us whether
+ * the request was a success.
+ */
+ $get = Array('appID' => $this->appId, 'appSecret' => $this->appSecret);
+ if ($expires !== null) { $get['expires'] = $expires; }
+
+ $response = file_get_contents($this->endpoint . '/token/create.json?' .
+ http_build_query($get));
+
+ if (!strstr($http_response_header[0], '200')) { throw new Exception('SSO rejected the token with ' . $http_response_header[0], 1605201109); }
+
+ $data = json_decode($response);
+
+ if (json_last_error() !== JSON_ERROR_NONE) { throw new Exception('SSO sent invalid json response - ' . json_last_error_msg(), 1608012100); }
+
+ return new Token($this, $data->token, $data->expires, $data->location);
+ }
+
+ /**
+ * Instances a token. As opposed to the createToken method, this token cannot
+ * be authorized afterwards.
+ *
+ * @param string $token
+ * @return Token
+ */
+ public function makeToken($token) {
+ return new Token($this, $token, null, null);
+ }
+
+ public function getUser($username, Token$token = null) {
+
+ if (!$username) { throw new Exception('Valid user id needed'); }
+
+ /*
+ * Assemble the request we need to retrieve the data. Please note that if
+ * there is no token we pass no parameters.
+ */
+ $request = new Request(
+ $this->endpoint . '/user/detail/' . $username . '.json',
+ $token && $token->isAuthenticated()? Array('token' => $token->getTokenInfo()->token, 'signature' => (string)$this->makeSignature()) : Array('signature' => (string)$this->makeSignature())
+ );
+
+ /*
+ * Fetch the JSON message from the endpoint. This should tell us whether
+ * the request was a success.
+ */
+ $resp = $request->send();
+ $data = json_decode($resp)->payload;
+
+ $user = new User($data->id, $data->username, $data->aliases, $data->groups, $data->verified, $data->registered_unix, $data->attributes, $data->avatar);
+ if ($data->email) { $user->setEmail($data->email); }
+
+ return $user;
+ }
+
+ /**
+ *
+ * @param string $signature
+ * @param string $token
+ * @param string $context
+ * @return AppAuthentication
+ */
+ public function authApp($signature, $token = null, $context = null) {
+ if ($token instanceof Token) {
+ $token = $token->getId();
+ }
+
+ $request = new Request(
+ $this->endpoint . '/auth/app.json',
+ array_filter(Array('token' => $token, 'signature' => (string)$this->makeSignature(), 'remote' => $signature, 'context' => $context))
+ );
+
+ $response = $request->send();
+
+ $json = json_decode($response);
+ $src = new App($json->local->id, $this->appSecret, $json->local->name);
+
+ if (isset($json->remote)) {
+ $app = new App($json->remote->id, null, $json->remote->name);
+ }
+ else {
+ $app = null;
+ }
+
+ if ($json->context) {
+ $contexts = [];
+ foreach ($json->context as $jsctx) {
+ $ctx = new Context($this, $app, $jsctx->id);
+ $ctx->setExists(!$jsctx->undefined);
+ $ctx->setGranted($jsctx->granted);
+ $contexts[$jsctx->id] = $ctx;
+ }
+ }
+ else {
+ $contexts = [];
+ }
+
+ $res = new AppAuthentication($this, $src, $app, $contexts, $json->token);
+
+ return $res;
+ }
+
+ public function sendEmail($userid, $subject, $body) {
+
+ $request = new Request(
+ $this->endpoint . '/email/send/' . $userid . '.json',
+ Array('appId' => $this->appId, 'appSecret' => $this->appSecret)
+ );
+
+ $response = $request->send(Array('body' => $body, 'subject' => $subject));
+ $data = json_decode($response)->payload;
+
+ return $data;
+ }
+
+ public function getEndpoint() {
+ return $this->endpoint;
+ }
+
+ public function getAppId() {
+ return $this->appId;
+ }
+
+ public function makeSignature($target = null, $contexts = []) {
+ $signature = new Signature(Hash::ALGO_DEFAULT, $this->appId, $this->appSecret, $target, $contexts);
+ return $signature;
+ }
+
+ public function getAppList() {
+ $url = $this->endpoint . '/appdrawer/index.json';
+ $request = new Request($url, ['signature' => (string)$this->makeSignature(), 'all' => 'yes']);
+
+ $response = $request->send();
+ $data = JSON::decode($response);
+
+ return $data;
+ }
+
+ public function getAppDrawer() {
+ $url = $this->endpoint . '/appdrawer/index.json';
+ $request = new Request($url, []);
+
+ $response = $request->send();
+ $data = JSON::decode($response);
+
+ return $data;
+ }
+
+ public function getAppDrawerJS() {
+ return $this->endpoint . '/appdrawer/index.js';
+ }
+
+ public function getGroupList() {
+ $url = $this->endpoint . '/group/index.json';
+ $resp = file_get_contents($url);
+
+ if (!strstr($http_response_header[0], '200')) {
+ throw new Exception('SSO rejected the request with ' . $http_response_header[0], 201605201109);
+ }
+
+ $data = json_decode($resp);
+ return $data->payload;
+ }
+
+ public function getGroup($id) {
+ $url = $this->endpoint . '/group/detail/' . $id . '.json';
+ $resp = file_get_contents($url);
+
+ if (!strstr($http_response_header[0], '200')) {
+ throw new Exception('SSO rejected the request with ' . $http_response_header[0], 201605201109);
+ }
+
+ $data = json_decode($resp);
+ return $data->payload;
+ }
+
+}
+
diff --git a/bin/classes/auth/SSOCache.php b/bin/classes/auth/SSOCache.php
new file mode 100644
index 0000000..55eaa7f
--- /dev/null
+++ b/bin/classes/auth/SSOCache.php
@@ -0,0 +1,32 @@
+<?php namespace auth;
+
+class SSOCache
+{
+
+ private $sso;
+
+ private $cache;
+
+ public function __construct($credentials) {
+ $this->sso = new SSO($credentials);
+ $this->cache = new \spitfire\cache\MemcachedAdapter();
+ $this->cache->setTimeout(3600*24);
+ }
+
+ public function getUser($id, $token = null) {
+
+ if ($token) { return $this->sso->getUser($id, $token); }
+
+ return unserialize($this->cache->get('sso_user_' . $id, function () use ($id) {
+ return serialize($this->sso->getUser($id));
+ }));
+ }
+
+ public function getSSO() {
+ return $this->sso;
+ }
+
+ public function __call($name, $arguments) {
+ return call_user_func_array(Array($this->sso, $name), $arguments);
+ }
+}
diff --git a/bin/classes/auth/Token.php b/bin/classes/auth/Token.php
new file mode 100644
index 0000000..77566fe
--- /dev/null
+++ b/bin/classes/auth/Token.php
@@ -0,0 +1,44 @@
+<?php namespace auth;
+
+use Exception;
+
+class Token
+{
+
+ private $sso;
+ private $token;
+ private $expires;
+ private $redirect;
+ private $cache = null;
+
+ public function __construct($sso, $token, $expires, $redirect) {
+ $this->sso = $sso;
+ $this->token = $token;
+ $this->expires = $expires;
+ $this->redirect = $redirect;
+ }
+
+ public function getId() {
+ return $this->token;
+ }
+
+ public function getRedirect($successURI, $failureURI = null) {
+ return $this->redirect . '?' . http_build_query(Array('returnurl' => strval($successURI), 'cancelurl' => strval($failureURI)));
+ }
+
+ public function getTokenInfo() {
+
+ if ($this->cache !== null) { return $this->cache; }
+
+ $response = file_get_contents($this->sso->getEndpoint() . '/auth/index/' . $this->token . '.json?signature=' . urlencode($this->sso->makeSignature()));
+
+ if (!isset($http_response_header)) { throw new Exception('SSO co