diff --git a/public_html/deployment/classes/plugins_renderer.class.php b/public_html/deployment/classes/plugins_renderer.class.php
index 288452c978d267e8b7c2aa11cbc208f39e0013fc..4d67ea7bfce113c2aec237a73c3f045f3e447d73 100644
--- a/public_html/deployment/classes/plugins_renderer.class.php
+++ b/public_html/deployment/classes/plugins_renderer.class.php
@@ -100,9 +100,7 @@ class plugin_renderer extends ciplugins {
     }
     public function getHtmlOutwindow(){
         $aConfig=$this->getPluginConfig();
-        return '<div id="'.$this->getHtmlOutIdWrapper().'" class="cmdoutbox draggable draggable-onpage">'
-        // .'<button class="btn-close float-right">X</button>'
-        .'<div class="header"><i class="'.$aConfig['icon'].'"></i> '.$this->_sPluginname.'</div>'
+        return '<div id="'.$this->getHtmlOutIdWrapper().'" class="cmdoutbox">'
         .'<div id="'.$this->getHtmlOutId().'" '
         .'class="out'
             .(isset($aConfig['window-cols'])  && $aConfig['window-cols']  ? ' cmd-cols-'.$aConfig['window-cols'] : ''   )
diff --git a/public_html/deployment/index.php b/public_html/deployment/index.php
index 1ebe3cd4d4bb9e05af25a4b69713342786d43fb9..0257f34ef7baad382af24302d67a60d7db31ec0d 100644
--- a/public_html/deployment/index.php
+++ b/public_html/deployment/index.php
@@ -85,9 +85,11 @@ $CI_plugins->setType('shellcmd');
 $aEnabledShellPlugins=$CI_plugins->getEnabledPlugins('shellcmd');
 $sHeader.= count($aEnabledShellPlugins) 
     ? '' 
-        ."\n<!-- shellcmd plugins :: js files -->\n"
+        ."\n<!-- for shellcmd plugins -->\n"
         .'<script src="/vendor/axelhahn/js/ubd.class.js"></script>'."\n"
-        .'<script src="/vendor/axelhahn/js/addi.js"></script>'."\n"
+        .'<script src="/vendor/winbox/0.2.82/winbox.min.js"></script>'."\n"
+        .'<link rel="stylesheet" type="text/css" href="/vendor/winbox/0.2.82/winbox.min.css"/>'."\n"
+        ."<!-- shellcmd scripts -->\n"
     : ''
     ;
 foreach ($aEnabledShellPlugins as $sPlugin){
@@ -99,8 +101,8 @@ foreach ($aEnabledShellPlugins as $sPlugin){
             .'<li >'
             .$oHtml->getLink(array(
                 'href'=>'#',
-                // 'onclick'=>'$(\'#'.$CI_plugins->getHtmlOutIdWrapper().'\').slideToggle(100);',
-                'onclick'=>'toggleShellWindow(\''.$CI_plugins->getHtmlOutIdWrapper().'\', this);',
+                // 'onclick'=>'toggleShellWindow(\''.$CI_plugins->getHtmlOutIdWrapper().'\', this);',
+                'onclick'=>'toggleShellWindow(\''.$CI_plugins->getHtmlOutId().'\', this);',
                 'role'=>'button',
                 'aria-expanded'=>'false',
                 'icon'=> (isset($aPluginConfig['icon']) ? $aPluginConfig['icon'] : ''),
diff --git a/public_html/deployment/js/functions.js b/public_html/deployment/js/functions.js
index a653e7bbd7a60d241ade87261e5127a912bb4780..2a68b11fe0c1ac9cca02e9160d1b624d63492f8a 100644
--- a/public_html/deployment/js/functions.js
+++ b/public_html/deployment/js/functions.js
@@ -42,14 +42,47 @@ function hideModalMessage(){
    return false;
 }
 
+var aWinBoxes={};
 /**
  * shellcmd plugin ... toggle output window
- * @param {string} idWrapperDiv  id of the wrapper
- * @param {object} oLink         a tag in the navbar with link for toggling window 
+ * @param {string} isPluginOutputDiv  id of the wrapper
+ * @param {object} oLink              a tag in the navbar with link for toggling window 
  */
-function toggleShellWindow(idWrapperDiv, oLink){
-    $('#'+idWrapperDiv).slideToggle(100);
-    $(oLink).parent().toggleClass('active');
+function toggleShellWindow(isPluginOutputDiv, oLink){
+    if(aWinBoxes[isPluginOutputDiv]){
+        aWinBoxes[isPluginOutputDiv].close();
+    } else {
+        var oWrapper=document.getElementById(isPluginOutputDiv);
+        aWinBoxes[isPluginOutputDiv] = WinBox({
+            title: oLink.innerText,
+            id: 'winbox-'+isPluginOutputDiv,
+            border: 5,
+            background: "#628",
+            class: [ "no-min", "no-max", /* "no-full", "no-resize", "no-move"*/ "ciwinbox" ],
+
+            // position + size
+            x: "center",
+            y: "center",
+            width: 10,
+            height: 10,
+
+            // viewport
+            top: 70,
+            right: 20,
+            bottom: 20,
+            left: 20,          
+
+            // take content from existing div
+            mount: oWrapper,
+            
+            onclose: function(){
+                delete aWinBoxes[isPluginOutputDiv];
+                $(oLink).parent().removeClass('active');
+            }
+        });
+        $(oLink).parent().addClass('active');
+        window.setTimeout("aWinBoxes['"+isPluginOutputDiv+"'].resize("+(oWrapper.clientWidth+25)+", "+(oWrapper.clientHeight+150)+").move('center', 'center')", 10);
+    }
 }
 
 // ----------------------------------------------------------------------
@@ -58,9 +91,6 @@ function toggleShellWindow(idWrapperDiv, oLink){
 
 $(document).ready(function() {
     initSoftscroll();
-    addi.init();
-    // $(".optionName").popover({trigger: "hover"});
-    // $("#content").hide().fadeIn(300);
 });
 
 
@@ -68,75 +98,6 @@ $(document).ready(function() {
 // action log
 // ----------------------------------------------------------------------
 
-/**
- * get filtered action log table
- * @returns {undefined}
-
-function __REMOVEME___updateActionlog(){
-    var sUrlBase="/webservice/?class=Actionlog&action=getLogs&type=json&args=";
-    var aArgs={};
-
-    var aFilteritems=["project", "where", "order", "limit"];
-    var aTableitems=["id", "time", "loglevel", "ip", "user", "project", "action", "message"];
-    
-    // --- create query url
-    
-    for (i=0; i<aFilteritems.length; i++){
-        sValue=$('#select' + aFilteritems[i]).val();
-        if(sValue){
-            aArgs[aFilteritems[i]]=sValue;
-        }
-    }
-    
-    var sWhere='';
-    for (j=0; j<aTableitems.length; j++){
-        sValue=$('#selectWhere' + aTableitems[j]).val();
-        if(sValue){
-            if (sWhere){
-                sWhere+' AND ';
-            }
-            sWhere+='`'+aTableitems[j]+'`'+sValue;
-        }
-    }
-    if (sWhere) {
-        aArgs["where"]=sWhere;
-    }
-
-    // --- get data
-
-    var sUrl=sUrlBase+'['+JSON.stringify(aArgs)+']';
-    $.post( sUrl, function( aData ) {
-        var sHtml='';
-        
-        // --- generate output
-        if (aData.length && aData[0]["id"]){
-            for (i=0; i<aData.length; i++){
-                sHtml+='<tr class="tractionlogs loglevel-'+aData[i]["loglevel"]+' '+aData[i]["project"]+'">';
-                for (j=0; j<aTableitems.length; j++){
-                    sHtml+='<td>'+aData[i][aTableitems[j]]+'</td>';
-                }
-                sHtml+='</tr>';
-            }
-        }
-        drawTimeline(aData);
-        
-        if (!sHtml){
-            sHtml=sMsgNolog; // variable is set in actionlog.class.php
-        } else {
-            sHead='';
-            for (j=0; j<aTableitems.length; j++){
-                sHead+='<th>'+aTableitems[j]+'</th>';
-            }
-            sHead='<thead><tr>'+sHead+'</tr></thead>';
-            sHtml='<table class="table table-condensed">'+sHead+'<tbody>'+sHtml+'</tbody></table>';
-        }
-        $('#tableLogactions').html(sHtml);
-        filterLogTable();
-    });
-    
-}
- */
-
 /**
  * get filtered action log table
  * @returns {undefined}
diff --git a/public_html/deployment/main.css b/public_html/deployment/main.css
index 3a2fb3dc048f4ba7975d10b6962d4dda869113e2..b15d900de914b854fa591a1d94e224b6c89de0d2 100644
--- a/public_html/deployment/main.css
+++ b/public_html/deployment/main.css
@@ -282,18 +282,19 @@ input[type="radio"]:checked+label, input[type="checkbox"]:checked+label{
 
 .tab-pane p {margin: 1em 10px;}
 
-/* ----- plugins ----- */
-.draggable-onpage{position: absolute;}
-.draggable-onscreen{position: fixed;}
-.isdragging{opacity: 0.9;}
-
-.cmdoutbox{background: rgba(0,0,0,0.9); color: #f0f0f0; box-shadow: 0.2em 0.2em 0.5em rgba(0,0,0,0.4); display: none;}
-.cmdoutbox .header{background:#628;padding: 0.1em 0.5em;}
-.cmdoutbox .out{color:#ccf; ;padding: 0.5em; font-family: monospace; overflow: scroll; white-space: nowrap; }
-.cmdoutbox button.btn-close{background:#e55; color: #fff; border: none;}
-
-.cmdoutbox .bar{background: rgba(255,255,255,0.1);}
-.cmdoutbox .progress{background: #85a;}
+/* ----- shell plugins ----- */
+
+.cmdoutbox{display: none;}
+.ciwinbox .wb-body{
+    background: #111 !important; 
+    color: #ccf; 
+    font-family: monospace; 
+    padding: 0.5em;
+    overflow: scroll; 
+    white-space: nowrap; 
+}
+.ciwinbox .bar{background: rgba(255,255,255,0.1);}
+.ciwinbox .progress{background: #85a;}
 
 .float-right{float: right;}
 
diff --git a/public_html/vendor/axelhahn/js/addi.js b/public_html/vendor/axelhahn/js/addi.js
deleted file mode 100644
index 1fac9723be2981bd52f1bae43e3f0b50fe1faf62..0000000000000000000000000000000000000000
--- a/public_html/vendor/axelhahn/js/addi.js
+++ /dev/null
@@ -1,410 +0,0 @@
-/**
- *  
- * ADDI = Axels Drag and drop implementation
- * 
- *   create draggable divs on screen if they have a defined class
- *   (named "draggable" by default - but you can use any other name)
- * 
- * @author    Axel Hahn
- * @version   1.0
- *
- * @this addi
- * 
- * @example
- * <pre>
- * // make all divs with class "draggable" be movable on screen<br>
- * addi.init();
- * </pre>
- * 
- * @constructor
- * @return nothing
- */
- var addi = function(){
-
-    return {
-        _saveData: [],
-        _dragClass: 'draggable',
-        _draggingClass: 'isdragging',
-
-        // last z-index value of last activated div 
-        _addi_zIndex: 100,
-        
-         // fixed rectangle earea whe a div can be moved
-         oFence: {
-            bFullscreen: true,
-            top: 0,
-            left: 0,
-            width: window.innerWidth,
-            height: window.innerHeight
-        },
-        
-        // override existing style values while moving the div
-        _savstyles:{
-            transition: 'auto'
-        },
-        
-        /**
-         * detect all draggable objects on a page and init each
-         * 
-         * @see initDiv()
-         * @param {string} sClass  optional: class of draggable elements; default: "draggable"
-         * @returns {undefined}
-         */
-        init(sClass){
-            if(sClass){
-                this._dragClass=sClass;
-            }
-            // scan all elements with class draggable and make them movable
-            var oList = document.getElementsByClassName(this._dragClass);
-            if(oList && oList.length){
-                for (var i = 0; i < oList.length; i++) {
-                    this.initDiv(oList[i], false);
-                }
-            }
-        },
-        // ------------------------------------------------------------
-        // private functions
-        // ------------------------------------------------------------
-        /**
-         * get a top left position {xpos, ypos} to fix current position and 
-         * make a div fully visible
-         * @see move()
-         * 
-         * @private
-         * @param {object} oDiv2Drag  movable object
-         * @param {type} xpos
-         * @param {type} ypos
-         * @returns {object}
-         */
-        _fixVisiblePosition(oDiv2Drag,xpos,ypos){
-            
-            this._updateFence(oDiv2Drag.style.paddingLeft);
-            var aStyles = window.getComputedStyle(oDiv2Drag);
-
-            var divDeltaX=0
-                + parseInt(aStyles.borderLeftWidth)
-                + parseInt(aStyles.borderRightWidth)
-                + parseInt(aStyles.marginLeft)
-                + parseInt(aStyles.marginRight)
-                + parseInt(aStyles.paddingLeft)
-                + parseInt(aStyles.paddingRight)
-                - (window.innerWidth - document.documentElement.clientWidth) // scrollbar
-                ;
-            var divDeltaY=0
-                + parseInt(aStyles.borderTopWidth)
-                + parseInt(aStyles.borderBottomWidth)
-                + parseInt(aStyles.marginTop)
-                + parseInt(aStyles.marginBottom)
-                // + parseInt(aStyles.paddingTop)
-                //+ parseInt(aStyles.paddingBottom)
-                ;
-
-            xpos=Math.max(this.oFence.left,xpos);
-            xpos=Math.min(this.oFence.left+this.oFence.width-oDiv2Drag.clientWidth-divDeltaX,xpos);
-
-            ypos=Math.max(this.oFence.top,ypos);
-            if (aStyles.position==='fixed') {                
-                ypos=Math.min(this.oFence.top+this.oFence.height-oDiv2Drag.clientHeight-divDeltaY,ypos);
-            }
-            
-            return {
-                xpos: xpos,
-                ypos: ypos
-            };
-            
-        },
-        /**
-         * helper: get a varname for localstorage to save / get last position
-         * 
-         * @private
-         * @param {string} s   id of movable element
-         * @returns {String}
-         */
-        _getVarname(s){
-            return 'addi.saveddiv-'+s;
-        },
-        /**
-         * save position of the given dom object
-         * 
-         * @private
-         * @param {object} oDiv2Drag  movable object
-         * @returns {undefined}
-         */
-         _save(oDiv2Drag){
-            aData={
-                left: oDiv2Drag.style.left.replace('px',''),
-                top:  oDiv2Drag.style.top.replace('px','')
-            };
-            localStorage.setItem(this._getVarname(oDiv2Drag.id),JSON.stringify(aData));
-        },
-
-        /**
-         * helper: save attributes in a variable: transition
-         * it is used for dragging: a transition slows down all movements
-         * @see _styleRestore()
-         * 
-         * @private
-         * @param {object} oDiv2Drag  movable object
-         * @returns {Boolean}
-         */
-        _styleSave(oDiv2Drag){
-            var aStyles = window.getComputedStyle(oDiv2Drag);
-            // create subitem for div id
-            if(this._saveData[oDiv2Drag.id] === undefined){
-                this._saveData[oDiv2Drag.id]=new Object();
-            };
-            for (var sAttr in this._savstyles){
-                // store value
-                this._saveData[oDiv2Drag.id][sAttr]=aStyles.getPropertyValue(sAttr);
-                // apply temp value
-                oDiv2Drag.style[sAttr]=this._savstyles[sAttr];
-            }
-            return true;
-        },
-        /**
-         * helper: retore attributes after moving
-         * @see _styleSave()
-         * @private
-         * @param {object} oDiv2Drag  movable object
-         * @returns {Boolean}
-         */
-        _styleRestore(oDiv2Drag){
-            for (var sAttr in this._savstyles){
-                oDiv2Drag.style[sAttr]=this._saveData[oDiv2Drag.id][sAttr];
-            }
-            return true;
-        },
-        /**
-         * helper: update size of this.oFence if it is set to fullscreen in 
-         * case of resizing of the browser window
-         * 
-         * @private
-         * @returns {undefined}
-         */
-        _updateFence(){
-            if(this.oFence.bFullscreen){
-                this.oFence={
-                    bFullscreen: true,
-                    top: 0,
-                    left: 0,
-                    width: window.innerWidth,
-                    height: window.innerHeight
-                };
-            };
-        },
-
-        /**
-         * generate an id for a draggable div that has no id yet
-         * 
-         * @private
-         * @returns {string}
-         */
-        _generateId(){
-            var sPrefix='generatedId-';
-            var iCount=1;
-            while (document.getElementById(sPrefix+iCount)){
-                iCount++;
-            }
-            return sPrefix+iCount;
-        },
-        
-        // ------------------------------------------------------------
-        // public functions
-        // ------------------------------------------------------------
-        
-        /**
-         * make a single div movable: 
-         * - add listener and 
-         * - restore last saved position (if class "saveposition" exists)
-         * 
-         * @param {object} oDiv2Drag   movable object
-         * @param {object} oDiv2Click  optional: clickable object
-         * @returns {undefined}
-         */
-        initDiv(oDiv2Drag,oDiv2Click){
-            var sDivId=oDiv2Drag.id;
-            if(!sDivId){
-                sDivId=this._generateId();
-                oDiv2Drag.id=sDivId;
-            }
-
-            // force position: fixed
-            var aStyles = oDiv2Drag.currentStyle || window.getComputedStyle(oDiv2Drag);
-
-            // console.log(oDiv2Drag.id + ' position: ' + aStyles.position);
-            if(!aStyles.position || aStyles.position=='static'  /* || aStyles.position!='fixed' */){
-                // oDiv2Drag.style.position='fixed';
-            }
-
-            // add events
-            // using atributes instead of addEventListener
-            o=(oDiv2Click ? oDiv2Click : oDiv2Drag);
-            o.onmousedown = function (event) {
-                addi._isDragging=true;
-                addi.startMoving(document.getElementById(sDivId),event);
-            };
-            o.onmouseup = function () {
-                addi._isDragging=false;
-                addi.stopMoving(document.getElementById(sDivId));
-            };
-            
-            // restore last position
-            if (oDiv2Drag.className.indexOf('saveposition')!==false){
-                this.load(oDiv2Drag);
-            }
-        },
-        /**
-         * load stored position and apply it to given dom object
-         * 
-         * @param {object} oDiv2Drag  movable object
-         * @returns {Array|Object|Boolean}
-         */
-         load(oDiv2Drag){
-            var id=this._getVarname(oDiv2Drag.id);
-
-            // detect the highest z-index
-            var aStyles = oDiv2Drag.currentStyle || window.getComputedStyle(oDiv2Drag);
-            if(aStyles.zIndex && aStyles.zIndex>0){
-                this._addi_zIndex=Math.max(parseInt(aStyles.zIndex), this._addi_zIndex);
-            }
-            oDiv2Drag.style.zIndex=this._addi_zIndex++;
-
-            var aData=localStorage.getItem(id) ? JSON.parse(localStorage.getItem(id)) : false;
-            if(aData && aData.left && aData.top){
-                this.move(oDiv2Drag,aData.left,aData.top, true);
-            }
-            return aData;
-        },
-        /**
-         * move obj to new position and store position in localstorage
-         * called from startMoving() and load()
-         * 
-         * @param {object} oDiv2Drag  movable object
-         * @param {integer} xpos      position x
-         * @param {integer} ypos      position y
-         * @param {boolean} bNoFix    flag: skip fixing the position based on window size (is set to true in the load method)
-         * @returns {undefined}
-         */
-        move(oDiv2Drag,xpos,ypos, bNoFix){
-            oDiv2Drag.style.bottom = 'auto';
-            
-            var aPos=bNoFix ? { 'xpos':xpos, 'ypos':ypos } : this._fixVisiblePosition(oDiv2Drag,xpos,ypos);
-            oDiv2Drag.style.left = aPos['xpos'] + 'px';
-            oDiv2Drag.style.top = aPos['ypos'] + 'px';            
-            this._save(oDiv2Drag);
-            return true;
-        },
-
-        /**
-         * called by onmousedown event
-         * 
-         * @param {object} oDiv2Drag  movable object
-         * @param {object} evt        event
-         * @returns {undefined}
-         */
-        startMoving(oDiv2Drag,evt){
-            if (oDiv2Drag.className.indexOf(this._dragClass)===false){
-                return false;
-            }
-            
-            evt = evt || window.event;
-            var posX = evt.clientX,
-                posY = evt.clientY;
-
-            // save some styles
-            this._styleSave(oDiv2Drag);
-
-
-            if(oDiv2Drag.className.indexOf(this._draggingClass)<0){
-                oDiv2Drag.className+= ' '+this._draggingClass;
-            }
-
-            // for FF only:
-            // if (navigator.appCodeName==='Mozilla' && navigator.userAgent.indexOf('Firefox/')>0){
-            document.body.style.userSelect='none';
-
-            iDivWidth = parseInt(oDiv2Drag.style.width),
-            iDivHeight = parseInt(oDiv2Drag.style.height);
-
-            oDiv2Drag.style.cursor='move';
-            oDiv2Drag.style.zIndex=this._addi_zIndex++;
-            
-            iDivLeft = oDiv2Drag.style.left ? oDiv2Drag.style.left.replace('px','') : oDiv2Drag.offsetLeft;
-            iDivTop  = oDiv2Drag.style.top? oDiv2Drag.style.top.replace('px','')  : oDiv2Drag.offsetTop;
-            var diffX = posX - iDivLeft,
-                diffY = posY - iDivTop;
-            document.onmousemove = function(evt){
-                evt = evt || window.event;
-                var posX = evt.clientX,
-                    posY = evt.clientY,
-                    aX = posX - diffX,
-                    aY = posY - diffY;
-                addi.move(oDiv2Drag,aX,aY);
-            };
-            return true;
-        },
-        /**
-         * called on mouse up event
-         * 
-         * @param {object} oDiv2Drag  movable object
-         * @returns {undefined}
-         */
-        stopMoving(oDiv2Drag){
-            oDiv2Drag.style.cursor='default';
-            // retore styles
-            this._styleRestore(oDiv2Drag);
-            document.body.style.userSelect='auto';
-            oDiv2Drag.className=oDiv2Drag.className.replace(' '+this._draggingClass, '');
-            oDiv2Drag.className=oDiv2Drag.className.replace(this._draggingClass, '');
-            
-            document.onmousemove = function(){};
-        },
-        /**
-         * reset position 
-         * 
-         * @param {bool}   bRemoveLocalstorage  flag: remove saved local variable too
-         * @returns {undefined}
-         */
-         resetPos(){
-            var oList = document.getElementsByClassName(this._dragClass);
-            if(oList && oList.length){
-                for (var i = 0; i < oList.length; i++) {
-                    oList[i].style = '';
-                    this._save(oList[i]);
-                }
-            }
-        },
-        /**
-         * reset style, onmousedown, onmouseup to make divs unmovable again
-         * 
-         * @param {bool}   bRemoveLocalstorage  flag: remove saved local variable too
-         * @returns {undefined}
-         */
-        reset(bRemoveLocalstorage){
-            // scan all elements with class draggable and reset
-            var oList = document.getElementsByClassName(this._dragClass);
-            if(oList && oList.length){
-                for (var i = 0; i < oList.length; i++) {
-                    this._resetDiv(oList[i],bRemoveLocalstorage);
-                }
-            }
-        },
-        /**
-         * reset a single div and make it unmovable
-         * 
-         * @private
-         * @param {object} oDiv2Drag            movable object 
-         * @param {bool}   bRemoveLocalstorage  flag: remove saved local variable too
-         * @returns {undefined}
-         */
-        _resetDiv(oDiv2Drag, bRemoveLocalstorage){
-            oDiv2Drag.onmousemove = null;
-            oDiv2Drag.onmouseup = null;
-            oDiv2Drag.onmousedown = null;
-            oDiv2Drag.style = '';
-            if(bRemoveLocalstorage){
-                localStorage.removeItem(this._getVarname(oDiv2Drag.id));
-            }
-        }
-    };
-}();
diff --git a/public_html/vendor/winbox/0.2.82/winbox.min.css b/public_html/vendor/winbox/0.2.82/winbox.min.css
new file mode 100644
index 0000000000000000000000000000000000000000..91088142aa699cde4c8a368e15ed7fcec40cfedb
--- /dev/null
+++ b/public_html/vendor/winbox/0.2.82/winbox.min.css
@@ -0,0 +1 @@
+@keyframes wb-fade-in{0%{opacity:0}to{opacity:.85}}.winbox{position:fixed;left:0;top:0;background:#0050ff;box-shadow:0 14px 28px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.22);transition:width .3s,height .3s,left .3s,top .3s;transition-timing-function:cubic-bezier(.3,1,.3,1);contain:layout size;text-align:left;touch-action:none}.wb-body,.wb-header{position:absolute;left:0}.wb-header{top:0;width:100%;height:35px;line-height:35px;color:#fff;overflow:hidden;z-index:1}.wb-body{top:35px;right:0;bottom:0;overflow:auto;-webkit-overflow-scrolling:touch;overflow-scrolling:touch;will-change:contents;background:#fff;margin-top:0!important;contain:strict;z-index:0}.wb-control *,.wb-icon{background-repeat:no-repeat}.wb-drag{height:100%;padding-left:10px;cursor:move}.wb-title{font-family:Arial,sans-serif;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wb-icon{display:none;width:20px;height:100%;margin:-1px 8px 0-3px;float:left;background-size:100%;background-position:center}.wb-e,.wb-w{width:10px;top:0}.wb-n,.wb-s{left:0;height:10px;position:absolute}.wb-n{top:-5px;right:0;cursor:n-resize;z-index:2}.wb-e{position:absolute;right:-5px;bottom:0;cursor:w-resize;z-index:2}.wb-s{bottom:-5px;right:0;cursor:n-resize;z-index:2}.wb-nw,.wb-sw,.wb-w{left:-5px}.wb-w{position:absolute;bottom:0;cursor:w-resize;z-index:2}.wb-ne,.wb-nw,.wb-sw{width:15px;height:15px;z-index:2;position:absolute}.wb-nw{top:-5px;cursor:nw-resize}.wb-ne,.wb-sw{cursor:ne-resize}.wb-ne{top:-5px;right:-5px}.wb-se,.wb-sw{bottom:-5px}.wb-se{position:absolute;right:-5px;width:15px;height:15px;cursor:nw-resize;z-index:2}.wb-control{float:right;height:100%;max-width:100%;text-align:center}.wb-control *{display:inline-block;width:30px;height:100%;max-width:100%;background-position:center;cursor:pointer}.no-close .wb-close,.no-full .wb-full,.no-header .wb-header,.no-max .wb-max,.no-min .wb-min,.no-resize .wb-body~div,.wb-body .wb-hide,.wb-show,.winbox.hide,.winbox.min .wb-body>*,.winbox.min .wb-full,.winbox.min .wb-min,.winbox.modal .wb-full,.winbox.modal .wb-max,.winbox.modal .wb-min{display:none}.winbox.max .wb-drag,.winbox.min .wb-drag{cursor:default}.wb-min{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAyIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNOCAwaDdhMSAxIDAgMCAxIDAgMkgxYTEgMSAwIDAgMSAwLTJoN3oiLz48L3N2Zz4=);background-size:14px auto;background-position:center calc(50% + 6px)}.wb-max{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIHZpZXdCb3g9IjAgMCA5NiA5NiI+PHBhdGggZD0iTTIwIDcxLjMxMUMxNS4zNCA2OS42NyAxMiA2NS4yMyAxMiA2MFYyMGMwLTYuNjMgNS4zNy0xMiAxMi0xMmg0MGM1LjIzIDAgOS42NyAzLjM0IDExLjMxMSA4SDI0Yy0yLjIxIDAtNCAxLjc5LTQgNHY1MS4zMTF6Ii8+PHBhdGggZD0iTTkyIDc2VjM2YzAtNi42My01LjM3LTEyLTEyLTEySDQwYy02LjYzIDAtMTIgNS4zNy0xMiAxMnY0MGMwIDYuNjMgNS4zNyAxMiAxMiAxMmg0MGM2LjYzIDAgMTItNS4zNyAxMi0xMnptLTUyIDRjLTIuMjEgMC00LTEuNzktNC00VjM2YzAtMi4yMSAxLjc5LTQgNC00aDQwYzIuMjEgMCA0IDEuNzkgNCA0djQwYzAgMi4yMS0xLjc5IDQtNCA0SDQweiIvPjwvc3ZnPg==);background-size:17px auto}.wb-close{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xIC0xIDE4IDE4Ij48cGF0aCBmaWxsPSIjZmZmIiBkPSJtMS42MTMuMjEuMDk0LjA4M0w4IDYuNTg1IDE0LjI5My4yOTNsLjA5NC0uMDgzYTEgMSAwIDAgMSAxLjQwMyAxLjQwM2wtLjA4My4wOTRMOS40MTUgOGw2LjI5MiA2LjI5M2ExIDEgMCAwIDEtMS4zMiAxLjQ5N2wtLjA5NC0uMDgzTDggOS40MTVsLTYuMjkzIDYuMjkyLS4wOTQuMDgzQTEgMSAwIDAgMSAuMjEgMTQuMzg3bC4wODMtLjA5NEw2LjU4NSA4IC4yOTMgMS43MDdBMSAxIDAgMCAxIDEuNjEzLjIxeiIvPjwvc3ZnPg==);background-size:15px auto;background-position:5px center}.wb-full{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjIuNSIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNOCAzSDVhMiAyIDAgMCAwLTIgMnYzbTE4IDBWNWEyIDIgMCAwIDAtMi0yaC0zbTAgMThoM2EyIDIgMCAwIDAgMi0ydi0zTTMgMTZ2M2EyIDIgMCAwIDAgMiAyaDMiLz48L3N2Zz4=);background-size:16px auto}.winbox.max .wb-body~div,.winbox.min .wb-body~div,.winbox.modal .wb-body~div,.winbox.modal .wb-drag,body.wb-lock iframe{pointer-events:none}.winbox.max{box-shadow:none}.winbox.max .wb-body{margin:0!important}.winbox iframe{position:absolute;width:100%;height:100%;border:0}body.wb-lock .winbox{will-change:left,top,width,height;transition:none}.winbox.modal:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background:inherit;border-radius:inherit}.winbox.modal:after{content:"";position:absolute;top:-50vh;left:-50vw;right:-50vw;bottom:-50vh;background:#0d1117;animation:wb-fade-in .2s ease-out forwards;z-index:-1}.no-animation{transition:none}.no-shadow{box-shadow:none}.no-header .wb-body{top:0}.no-move:not(.min) .wb-title{pointer-events:none}.wb-body .wb-show{display:revert}
\ No newline at end of file
diff --git a/public_html/vendor/winbox/0.2.82/winbox.min.js b/public_html/vendor/winbox/0.2.82/winbox.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..30b93e74181f67f4e4245c0ddea3941f7fdb6a86
--- /dev/null
+++ b/public_html/vendor/winbox/0.2.82/winbox.min.js
@@ -0,0 +1,33 @@
+/**
+ * WinBox.js v0.2.82
+ * Author and Copyright: Thomas Wilkerling
+ * Licence: Apache-2.0
+ * Hosted by Nextapps GmbH
+ * https://github.com/nextapps-de/winbox
+ */
+(function(){'use strict';var e,aa=document.createElement("div");aa.innerHTML="<div class=wb-header><div class=wb-control><span class=wb-min></span><span class=wb-max></span><span class=wb-full></span><span class=wb-close></span></div><div class=wb-drag><div class=wb-icon></div><div class=wb-title></div></div></div><div class=wb-body></div><div class=wb-n></div><div class=wb-s></div><div class=wb-w></div><div class=wb-e></div><div class=wb-nw></div><div class=wb-ne></div><div class=wb-se></div><div class=wb-sw></div>";function h(a,b,c,f){a&&a.addEventListener(b,c,f||!1)}function k(a,b){var c=window,f=l;c&&c.removeEventListener(a,b,f||!1)}function m(a,b){a.stopPropagation();b&&a.preventDefault()}function t(a,b,c){c=""+c;a["_s_"+b]!==c&&(a.style.setProperty(b,c),a["_s_"+b]=c)};/*
+ self.max &&*/
+var u=[],x=[],ba={capture:!0,passive:!1},l={capture:!0,passive:!0},A,ea=0,B=10,E,F,fa,J,K,ha;
+function P(a,b){if(!(this instanceof P))return new P(a);A||ia();if(a){if(b){var c=a;a=b}if("string"===typeof a)c=a;else{var f=a.id;var d=a.index;var n=a.root;var p=a.template;c=c||a.title;var v=a.icon;var L=a.mount;var Q=a.html;var g=a.url;var q=a.width;var r=a.height;var w=a.minwidth;var C=a.minheight;var y=a.maxwidth;var z=a.maxheight;var ca=a.autosize;var D=a.overflow;var G=a.min;var H=a.max;var I=a.hidden;var da=a.modal;var W=a.x||(da?"center":0);var X=a.y||(da?"center":0);var M=a.top;var N=a.left;
+var R=a.bottom;var S=a.right;var ja=a.background;var O=a.border;var T=a.header;var Y=a["class"];var ka=a.oncreate;var pa=a.onclose;var qa=a.onfocus;var ra=a.onblur;var sa=a.onmove;var ta=a.onresize;var ua=a.onfullscreen;var va=a.onmaximize;var wa=a.onminimize;var xa=a.onrestore;var ya=a.onhide;var za=a.onshow;var Aa=a.onload}}this.g=(p||aa).cloneNode(!0);this.g.id=this.id=f||"winbox-"+ ++ea;this.g.className="winbox"+(Y?" "+("string"===typeof Y?Y:Y.join(" ")):"")+(da?" modal":"");this.g.winbox=this;
+this.window=this.g;this.body=this.g.getElementsByClassName("wb-body")[0];this.h=T||35;x.push(this);ja&&this.setBackground(ja);O?t(this.body,"margin",O+(isNaN(O)?"":"px")):O=0;T&&(b=this.g.getElementsByClassName("wb-header")[0],t(b,"height",T+"px"),t(b,"line-height",T+"px"),t(this.body,"top",T+"px"));c&&this.setTitle(c);v&&this.setIcon(v);L?this.mount(L):Q?this.body.innerHTML=Q:g&&this.setUrl(g,Aa);M=M?U(M,K):0;R=R?U(R,K):0;N=N?U(N,J):0;S=S?U(S,J):0;c=J-N-S;v=K-M-R;y=y?U(y,c):c;z=z?U(z,v):v;w=w?U(w,
+y):150;C=C?U(C,z):this.h;ca?((n||A).appendChild(this.body),q=Math.max(Math.min(this.body.clientWidth+2*O+1,y),w),r=Math.max(Math.min(this.body.clientHeight+this.h+O+1,z),C),this.g.appendChild(this.body)):(q=q?U(q,y):Math.max(y/2,w)|0,r=r?U(r,z):Math.max(z/2,C)|0);W=W?U(W,c,q):N;X=X?U(X,v,r):M;this.x=W;this.y=X;this.width=q;this.height=r;this.s=w;this.o=C;this.m=y;this.l=z;this.top=M;this.right=S;this.bottom=R;this.left=N;this.index=d;this.j=D;this.focused=this.hidden=this.full=this.max=this.min=!1;
+this.onclose=pa;this.onfocus=qa;this.onblur=ra;this.onmove=sa;this.onresize=ta;this.onfullscreen=ua;this.onmaximize=va;this.onminimize=wa;this.onrestore=xa;this.onhide=ya;this.onshow=za;I?this.hide():this.focus();if(d||0===d)this.index=d,t(this.g,"z-index",d),d>B&&(B=d);H?this.maximize():G?this.minimize():this.resize().move();la(this);(n||A).appendChild(this.g);ka&&ka.call(this,a)}P["new"]=function(a){return new P(a)};P.stack=function(){return x};
+function U(a,b,c){"string"===typeof a&&("center"===a?a=(b-c)/2+.5|0:"right"===a||"bottom"===a?a=b-c:(c=parseFloat(a),a="%"===(""+c!==a&&a.substring((""+c).length))?b/100*c+.5|0:c));return a}
+function ia(){A=document.body;A[F="requestFullscreen"]||A[F="msRequestFullscreen"]||A[F="webkitRequestFullscreen"]||A[F="mozRequestFullscreen"]||(F="");fa=F&&F.replace("request","exit").replace("mozRequest","mozCancel").replace("Request","Exit");h(window,"resize",function(){ma();na()});h(A,"mousedown",function(){ha=!1},!0);h(A,"mousedown",function(){if(!ha){var a=x.length;if(a)for(--a;0<=a;a--){var b=x[a];if(b.focused){b.blur();break}}}});ma()}
+function la(a){V(a,"drag");V(a,"n");V(a,"s");V(a,"w");V(a,"e");V(a,"nw");V(a,"ne");V(a,"se");V(a,"sw");h(a.g.getElementsByClassName("wb-min")[0],"click",function(b){m(b);a.min?a.restore().focus():a.minimize()});h(a.g.getElementsByClassName("wb-max")[0],"click",function(b){m(b);a.max?a.restore().focus():a.maximize().focus()});F?h(a.g.getElementsByClassName("wb-full")[0],"click",function(b){m(b);a.fullscreen().focus()}):a.addClass("no-full");h(a.g.getElementsByClassName("wb-close")[0],"click",function(b){m(b);
+a.close()||(a=null)});h(a.g,"mousedown",function(){ha=!0},!0);h(a.body,"mousedown",function(){a.focus()},!0)}function Z(a){u.splice(u.indexOf(a),1);na();a.removeClass("min");a.min=!1;a.g.title=""}function na(){for(var a=u.length,b={},c={},f=0,d;f<a;f++)d=u[f],d=d.left+":"+d.top,c[d]?c[d]++:(b[d]=0,c[d]=1);f=0;for(var n,p;f<a;f++)d=u[f],n=d.left+":"+d.top,p=Math.min((J-d.left-d.right)/c[n],250),d.resize(p+1|0,d.h,!0).move(d.left+b[n]*p|0,K-d.bottom-d.h,!0),b[n]++}
+function V(a,b){function c(g){m(g,!0);a.focus();if("drag"===b){if(a.min){a.restore();return}if(!a.g.classList.contains("no-max")){var q=Date.now(),r=q-Q;Q=q;if(300>r){a.max?a.restore():a.maximize();return}}}a.min||(A.classList.add("wb-lock"),(p=g.touches)&&(p=p[0])?(g=p,h(window,"touchmove",f,l),h(window,"touchend",d,l)):(h(window,"mousemove",f,l),h(window,"mouseup",d,l)),v=g.pageX,L=g.pageY)}function f(g){m(g);p&&(g=g.touches[0]);var q=g.pageX;g=g.pageY;var r=q-v,w=g-L,C=a.width,y=a.height,z=a.x,
+ca=a.y,D;if("drag"===b){if(a.g.classList.contains("no-move"))return;a.x+=r;a.y+=w;var G=D=1}else{if("e"===b||"se"===b||"ne"===b){a.width+=r;var H=1}else if("w"===b||"sw"===b||"nw"===b)a.x+=r,a.width-=r,G=H=1;if("s"===b||"se"===b||"sw"===b){a.height+=w;var I=1}else if("n"===b||"ne"===b||"nw"===b)a.y+=w,a.height-=w,D=I=1}H&&(a.width=Math.max(Math.min(a.width,a.m,J-a.x-a.right),a.s),H=a.width!==C);I&&(a.height=Math.max(Math.min(a.height,a.l,K-a.y-a.bottom),a.o),I=a.height!==y);(H||I)&&a.resize();G&&
+(a.max&&(a.x=(q<J/3?a.left:q>J/3*2?J-a.width-a.right:J/2-a.width/2)+r),a.x=Math.max(Math.min(a.x,a.j?J-30:J-a.width-a.right),a.j?30-a.width:a.left),G=a.x!==z);D&&(a.max&&(a.y=a.top+w),a.y=Math.max(Math.min(a.y,a.j?K-a.h:K-a.height-a.bottom),a.top),D=a.y!==ca);if(G||D)a.max&&a.restore(),a.move();if(H||G)v=q;if(I||D)L=g}function d(g){m(g);A.classList.remove("wb-lock");p?(k("touchmove",f),k("touchend",d)):(k("mousemove",f),k("mouseup",d))}var n=a.g.getElementsByClassName("wb-"+b)[0];if(n){var p,v,L,
+Q=0;h(n,"mousedown",c,ba);h(n,"touchstart",c,ba)}}function ma(){var a=document.documentElement;J=a.clientWidth;K=a.clientHeight}e=P.prototype;e.mount=function(a){this.unmount();a.i||(a.i=a.parentNode);this.body.textContent="";this.body.appendChild(a);return this};e.unmount=function(a){var b=this.body.firstChild;if(b){var c=a||b.i;c&&c.appendChild(b);b.i=a}return this};
+e.setTitle=function(a){var b=this.g.getElementsByClassName("wb-title")[0];a=this.title=a;var c=b.firstChild;c?c.nodeValue=a:b.textContent=a;return this};e.setIcon=function(a){var b=this.g.getElementsByClassName("wb-icon")[0];t(b,"background-image","url("+a+")");t(b,"display","inline-block");return this};e.setBackground=function(a){t(this.g,"background",a);return this};
+e.setUrl=function(a,b){var c=this.body.firstChild;c&&"iframe"===c.tagName.toLowerCase()?c.src=a:(this.body.innerHTML='<iframe src="'+a+'"></iframe>',b&&(this.body.firstChild.onload=b));return this};e.focus=function(a){if(!1===a)return this.blur();if(!this.focused){a=x.length;if(1<a)for(var b=1;b<=a;b++){var c=x[a-b];if(c.focused){c.blur();x.push(x.splice(x.indexOf(this),1)[0]);break}}t(this.g,"z-index",++B);this.index=B;this.addClass("focus");this.focused=!0;this.onfocus&&this.onfocus()}return this};
+e.blur=function(a){if(!1===a)return this.focus();this.focused&&(this.removeClass("focus"),this.focused=!1,this.onblur&&this.onblur());return this};e.hide=function(a){if(!1===a)return this.show();if(!this.hidden)return this.onhide&&this.onhide(),this.hidden=!0,this.addClass("hide")};e.show=function(a){if(!1===a)return this.hide();if(this.hidden)return this.onshow&&this.onshow(),this.hidden=!1,this.removeClass("hide")};
+e.minimize=function(a){if(!1===a)return this.restore();E&&oa();this.max&&(this.removeClass("max"),this.max=!1);this.min||(u.push(this),na(),this.g.title=this.title,this.addClass("min"),this.min=!0,this.focused&&(this.blur(),Ba()),this.onminimize&&this.onminimize());return this};function Ba(){var a=x.length;if(a)for(--a;0<=a;a--){var b=x[a];if(!b.min){b.focus();break}}}
+e.restore=function(){E&&oa();this.min&&(Z(this),this.resize().move(),this.onrestore&&this.onrestore());this.max&&(this.max=!1,this.removeClass("max").resize().move(),this.onrestore&&this.onrestore());return this};e.maximize=function(a){if(!1===a)return this.restore();E&&oa();this.min&&Z(this);this.max||(this.addClass("max").resize(J-this.left-this.right,K-this.top-this.bottom,!0).move(this.left,this.top,!0),this.max=!0,this.onmaximize&&this.onmaximize());return this};
+e.fullscreen=function(a){this.min&&(Z(this),this.resize().move());if(!E||!oa())this.body[F](),E=this,this.full=!0,this.onfullscreen&&this.onfullscreen();else if(!1===a)return this.restore();return this};function oa(){E.full=!1;if(document.fullscreen||document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement)return document[fa](),!0}
+e.close=function(a){if(this.onclose&&this.onclose(a))return!0;this.min&&Z(this);x.splice(x.indexOf(this),1);this.unmount();this.g.remove();this.g.textContent="";this.g=this.body=this.g.winbox=null;this.focused&&Ba()};e.move=function(a,b,c){a||0===a?c||(this.x=a?a=U(a,J-this.left-this.right,this.width):0,this.y=b?b=U(b,K-this.top-this.bottom,this.height):0):(a=this.x,b=this.y);t(this.g,"left",a+"px");t(this.g,"top",b+"px");this.onmove&&this.onmove(a,b);return this};
+e.resize=function(a,b,c){a||0===a?c||(this.width=a?a=U(a,this.m):0,this.height=b?b=U(b,this.l):0,a=Math.max(a,this.s),b=Math.max(b,this.o)):(a=this.width,b=this.height);t(this.g,"width",a+"px");t(this.g,"height",b+"px");this.onresize&&this.onresize(a,b);return this};
+e.addControl=function(a){var b=a["class"],c=a.image,f=a.click;a=a.index;var d=document.createElement("span"),n=this.g.getElementsByClassName("wb-control")[0],p=this;b&&(d.className=b);c&&t(d,"background-image","url("+c+")");f&&(d.onclick=function(v){f.call(this,v,p)});n.insertBefore(d,n.childNodes[a||0]);return this};e.removeControl=function(a){(a=this.g.getElementsByClassName(a)[0])&&a.remove();return this};e.addClass=function(a){this.g.classList.add(a);return this};
+e.removeClass=function(a){this.g.classList.remove(a);return this};e.toggleClass=function(a){return this.g.classList.contains(a)?this.removeClass(a):this.addClass(a)};window.WinBox=P;}).call(this);