if (window.ioi === undefined) {
	ioi = window.ioi = function() {
		'use strict';
	
		var inner_html_div = document.createElement('div');
		var default_return = [];
	
		const SELECTOR_IGNORE_ATTRIBUTE = ['id', 'class', 'style',
		'onerror', 'onload',
		'onblur', 'onchange', 'oncontextmenu', 'onfocus', 'oninput', 'onselect', 'onsubmit',
		'onkeydown', 'onkeypress', 'onkeyup',
		'onclick', 'ondblclick', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onwheel',
		'ondrag', 'ondragend', 'ondrop'];
	
		var ioi = function (_arg1, _arg2, _arg3, ..._args) {
			// if (!_arg1) return false;

			// Check if it's a template literal : ioi`<div class=${'aaa'}>bbb</div>`
			// https://stackoverflow.com/questions/56891111/how-to-detect-whether-a-function-was-called-normally-or-as-a-tagged-template-lit
			// if (ioi.isArr(_arg1) && ioi.isArr(_arg1.raw) && _arg1.length === arguments.length) return ioi.htm.apply(this, arguments);
			if (ioi.isLit(arguments)) return ioi.htm.apply(this, arguments);
			// if (ioi.isArr(_arg1) && _arg1.length > 0 && ioi.isStr(_arg1[0]) && _arg1.length === arguments.length) return ioi.htm.apply(this, arguments);

			// Check if it's an hyperscript : ioi(('div', { class: 'aaa' }, 'bbb')
			if (ioi.isStr(_arg1) && ioi.isSet(_arg2) && ioi.isPureObj(_arg2)) return ioi.xhtm.apply(this, arguments);

			// Check if it's a function : ioi(()=>{ console.log('test')})
			// Will call even if args are inverted : ioi(()=>{ console.log('test')}, 1000) / ioi(1000, ()=>{ console.log('test')})
			if (ioi.isFn(_arg1) || !ioi.isFn(_arg1) && ioi.isFn(_arg2)) return ioi.ready(_arg1, _arg2);
	
			// Check if it's a node (list) or a selector : ioi('#node_id, .node_class')
			if (ioi.isStr(_arg1) || ioi.isNode(_arg1) || ioi.isNodeList(_arg1)) {
				if(ioi.isHTMLString(_arg1)) _arg1 = ioi.toNode(_arg1); // Convert string to node
				else if(ioi.isStr(_arg1)) _arg1 = ioi.query(_arg1, _arg2); // Query string in provided node or document
	
				// if position is provided as the third argument then transfer it to the second argument
				if(ioi.isNum(_arg3)) _arg2 = _arg3;

				// Return element at desired index, negative index to get from the end of the list
				if (ioi.isNum(_arg2)) _arg1 = _arg1.length  && !ioi.isNode(_arg1) ? _arg1[_arg2 < 0 ? _arg1.length + _arg2 : _arg2] : _arg1; 
				// If it's not a single node then return an array instead of a NodeList, collection, etc
				else if (ioi.isNodeList(_arg1)) _arg1 = _arg1.length === 1 ?_arg1[0] : Array.prototype.slice.call(_arg1); 
				// else if (ioi.isNodeList(_arg1)) _arg1 = Array.prototype.slice.call(_arg1); 
				// else if (_arg1.length !== undefined && !ioi.isNode(_arg1)) _arg1 = Array.prototype.slice.call(_arg1); 
				// else _arg1 = _arg1.length === undefined || ioi.isNode(_arg1) ? [_arg1] : Array.prototype.slice.call(_arg1); 

				if (ioi.isArr(_arg1) && _arg1.length === 0) return default_return; // If we have an empty, return it without extending it
				// if (ioi.isArr(_arg1) && _arg1.length === 0) return _arg1; // If we have an empty, return it without extending it

				// Extend node functions, extend only once if _arg1 is a node
				_arg1 = ioi.fn.extend(_arg1);

				if (_arg1.length === undefined) _arg1.length = 1;
	
				return _arg1;
			}

			console.warn('ioi : no valid usage found, returning body...');
			return ioi.fn.extend(document.body);
	
			console.error(`ioi : the first arg must be one of the following :
			-Function
			-Template literal
			-Hyper Script literal
			-String
			-Node / HTML Element
			-Node list / HTML Collection`);
	
			return false;
		};
	
		ioi.stringToNode = ioi.htmlToNode = ioi.toHTML = ioi.toNode = (_str) => {
			if(ioi.isHTMLString(_str)) {
				// var parent = document.createElement('div');
				inner_html_div.innerHTML = _str.replace(/\s{2,}</gmi, '<');
				return inner_html_div.childNodes;
			}
	
			return _str;
		};
		
		ioi.isNull = _v => _v === null;
		ioi.isFalsy = ioi.isFalse = _b => ioi.isPureObj(_b) ? Object.keys(_b).length === 0 : (ioi.isArr(_b) ? _b.length === 0 : (/false|faux|null|undefined|NaN|0/i.test(_b) ? true : !_b));
		ioi.isTruthy = ioi.isTrue = _b => !ioi.isFalse(_b);
		ioi.isEmpty = _s => _s === undefined || _s === null || isNaN(_s) || _s === '';
		ioi.isDefined = ioi.isDef = ioi.isSet = _v => typeof _v !== 'undefined';
		ioi.isNumber = ioi.isNum = _n => typeof _n === 'number';
		ioi.isString = ioi.isStr = _s => typeof _s === 'string';
		ioi.isObject = ioi.isObj = _o => typeof _o === 'object';
		ioi.isPureObject = ioi.isPureObj = _o => _o.constructor.name === "Object";
		ioi.isLiteral = ioi.isLit = (_a) => _a.length > 0 && Array.isArray(_a[0].raw) && Array.isArray(_a[0]) && _a[0].length === _a.length && Object.isFrozen(_a[0]);
		// ioi.isLiteral = ioi.isLit = (_s, _a) => Array.isArray(_s.raw) && Array.isArray(_s) && _s.length === _a.length && Object.isFrozen(_s);
		ioi.isArray = ioi.isArr = _a => Array.isArray(_a); // _a instanceof Array
		ioi.isFunction = ioi.isFn = _f => typeof _f === 'function';
		ioi.isDocument = ioi.isDoc = _d => _d instanceof Document;
		ioi.isNode = _n => _n instanceof Node || _n instanceof Element || _n instanceof HTMLElement;
		ioi.isNodeText = _n => _n instanceof Text;
		ioi.isNodeList = _l => _l instanceof NodeList || _l instanceof HTMLCollection || Array.isArray(_l) || String(_l) === '[object NodeList]';
		
		ioi.isEmail = ioi.isMail = _e => /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(_e.toLowerCase());
		ioi.isHTMLString = _s => ioi.isStr(_s) && /^\s*</gmi.test(_s);

		ioi.randomLetter = () => String.fromCharCode(65 + Math.floor(Math.random() * 26));
		ioi.randomID = (_l=6) => ioi.randomLetter() + Math.random().toString(36).substring(2, _l + 1);
		ioi.randomColor = () => '#' + Math.floor(Math.random() * 16777215).toString(16);
		ioi.urlForceLoad = _u =>  _u + (_u.indexOf('?') > -1 ? '&v=' : '?v=') + ioi.randomID();
		
		ioi.getNodeIndex = ioi.nodeIndex = _node => [].indexOf.call(_node.parentNode.children, _node);

		ioi.queryAll = ioi.query = (_selector, _nodeParent) =>  (ioi.isNode(_nodeParent) ? _nodeParent : document).querySelectorAll(_selector);
		ioi.isSelectorUnique = (_selector, _nodeParent) => ioi.query(_selector, _nodeParent).length === 1;
		ioi.isSelectorUniqueInParent = (_selector, _nodeParent) => ioi.isSelectorUnique(':scope ' + (/\s*>/gmi.test(_selector) ? '' : ' > ') + _selector, _nodeParent);
	
		// var a = 'esta', b = ['solo', 'uno'], c = ['class', 'attr', ['dos', 'abla']], d = 'oldo, etha ranha,lyr ,erne,,,arka';
		// ioi.flattenArr(a, b, c, d);
		ioi.flattenArr = (..._args) => { return _args.flat(2); }; // ES2019
		ioi.flattenArrFast = (..._args) => { return [].concat(..._args); };
		ioi.flattenArg = (..._args) => {
			var res = [];
			
			if (_args.length === 1 && (ioi.isArr(_args[0]) || ioi.isNodeList(_args[0]))) _args = _args[0];

			for(var a of _args) {
				if(typeof a === 'string') res.push(...a.replace(/\s*,+\s*|\s+/gmi, ',').split(','));
				else res.push(...a);
			}
			return res;
		};
		ioi.flattenArgFull = (..._args) => {
			var res = [];
			
			if (_args.length === 1 && (ioi.isArr(_args[0]) || ioi.isNodeList(_args[0]))) _args = _args[0];

			for(var a of _args) {
				if(typeof a === 'string') res = res.concat(...a.replace(/\s*,+\s*|\s+/gmi, ',').split(','));
				else res = res.concat(...a);
			}
			return res;
		};


		ioi.isReady = false;
		ioi.scriptPath = ioi.query('script[src*="/ioi.js"]')[0].src; // script[src$="ioi.js"]
		ioi.scriptRootPath = ioi.scriptPath.replace(/ioi\.js.*$/gmi, '').replace(window.location.origin, '');
	
	
		ioi.ready = (_callback, _delay = true) => {
			// Swap arguments if needed...
			if (!ioi.isFn(_callback) && ioi.isFn(_delay)) [_callback, _delay] = [_delay, _callback];

			if (ioi.isStr(_delay) || ioi.isArr(_delay)) return ioi.ready(() => { ioi.readyRequire(_delay, _callback); });
	
			if (ioi.isReady) return ioi.isNum(_delay) ? setTimeout(_callback, _delay): _callback();
	
			// Check if DOM is already available
			// ONLY CALLED WHEN ioi.js IS LOADED AFTER DOM IS READY
			// (ie: ioi.js defered, imported with a bookmarklet, ...)
			if (document.readyState === "complete" || document.readyState === "interactive") {
				if (ioi.isNum(_delay)) {
					setTimeout(_callback, _delay);
				} else if (_delay === true) {
					// call on next available tick
					// setTimeout(fn, 1) : 
					// This allows the calling code to always assume they
					// are async callbacks that will be called later, even
					// if later is as soon as the current thread of JS
					// finishes and it preserves calling order.
					setTimeout(_callback, 1);
				} else {
					return _callback();
				}
			} else {
				if (ioi.isNum(_delay)) {
					document.addEventListener("DOMContentLoaded", () => { setTimeout(_callback, _delay) });
				} else {
					document.addEventListener("DOMContentLoaded", _callback);
				}
			}
			if(_delay === 1000) console.log(8)
	
			return undefined;
		};
	
		ioi.require = (_extensionName, _type, _force = false) => {
			if (/\s|,/gmi.test(_extensionName)) {
				_extensionName = _extensionName.replace(/\s*,+\s*|\s+/gmi, ' ').split(' ');
				for (var module of _extensionName) {
					ioi.require(module);
				}
				return;
			}
	
			var ext = '.js';
			if(['css', '.css', 'style'].indexOf(_type) > -1 || /\.css\s*$/gmi.test(_extensionName)) {
				_type = 'addStyle';
				ext = '.css';
			} else if(['json', '.json'].indexOf(_type) > -1 || /\.json\s*$/gmi.test(_extensionName)) {
				_type = 'addScript';
				ext = '.json';
			} else {
				_type = 'addScript';
			}
	
			if (!(/\/|^\s*http/gmi.test(_extensionName))) {
				_extensionName = _extensionName.replace(/^\s*ioi\.|\.(css|json|js)\s*$/gmi, '');
	
				_extensionName = ioi.scriptRootPath + 'ioi.' + _extensionName + ext;
			}
	
			if(_force) _extensionName = ioi.urlForceLoad(_extensionName);
	
			ioi[_type](_extensionName, ext);
		};
	
		ioi.readyRequire = (_required, _callback) => {
			if (ioi.isStr(_required)) _required = _required.replace(/\s*,+\s*|\s+/gmi, ' ').split(' ');
			_required = _required.filter(x => x);
	
			if(_required.length === 0) return _callback();
	
			var require_count = _required.length;
	
			var require_callback = () => {
				require_count--;
	
				if (require_count === 0) _callback();
			};
	
			for (var module of _required) {
				if (ioi.hop(module)) {
					require_callback();
				} else {
					ioi.event(`module:${module}:loaded`, require_callback);
					ioi.require(module);
				}
			}
	
			return undefined;
		};
	
		ioi.event = (_str, _data) => {
			if (ioi.isFn(_data)) {
				ioi(document).on('ioi.event.' + _str, function (e) {
					_data.apply(this, [e.type.replace('ioi.event.', ''), e.detail]);
				});
			} else {
				if (_data) _data = { detail: _data };
				const event = new CustomEvent('ioi.event.' + _str, _data);
				document.dispatchEvent(event)
			}
		};
		ioi.sendEvent = ioi.event.send = ioi.event;
		ioi.onEvent = ioi.event.on = ioi.event;
	
		ioi.extend = (_name, _value, _callback = null, _required) => {
			// Swap arguments if needed...
			if (!ioi.isFn(_callback) && ioi.isFn(_required)) [_callback, _required] = [_required, _callback];

			if (_required) {
				ioi(() => {
					ioi.extend(_name, _value, _callback);
				}, _required);
	
				return undefined
			}
	
			if(!ioi.isReady) {
				ioi.event(`module:${_name}:waiting`);
				ioi(() => {
					ioi.extend(_name, _value, _callback);
				});
	
				return undefined;
			}
	
			if(ioi.hop(_name)) {
				console.warn('ioi.extend : property "' + _name + '" already defined');
				return false;
			}
	
			ioi[_name] = _value;
	
			if(ioi.isFn(_callback)) {
				ioi.event(`module:${_name}:loading`);
				_callback();
				ioi.event(`module:${_name}:loaded`);
				return true;
			}
			else return true;
		};


		// https://github.com/dy/xhtm
		const t="",e="";function o(o){let s,a,c,n,d=this,h=0,f=[null],g=0,u=[],m=0,b=0,y=!1;const $=(t,o=[],r)=>{let l=0;return(t=r||t!==e?t.replace(/\ue001/g,t=>u[m++]):u[m++].slice(1,-1))?(t.replace(/\ue000/g,(e,r)=>(r&&o.push(t.slice(l,r)),l=r+1,o.push(arguments[++g]))),l<t.length&&o.push(t.slice(l)),o.length>1?o:o[0]):t},k=()=>{[f,n,...s]=f,f.push(d(n,...s)),y===b--&&(y=!1)};return o.join(t).replace(/<!--[^]*?-->/g,"").replace(/<!\[CDATA\[[^]*\]\]>/g,"").replace(/('|")[^\1]*?\1/g,t=>(u.push(t),e)).replace(/(?:^|>)((?:[^<]|<[^\w\ue000\/?!>])*)(?:$|<)/g,(t,e,o,s)=>{let d,u;if(o&&s.slice(h,o).replace(/(\S)\/$/,"$1 /").split(/\s+/).map((t,e)=>{if("/"===t[0]){if(t=t.slice(1),l[t])return;u=d||t||1}else if(e){if(t){let e=f[2]||(f[2]={});"..."===t.slice(0,3)?Object.assign(e,arguments[++g]):([a,c]=t.split("="),Array.isArray(c=e[$(a)]=!c||$(c))&&(c.toString=c.join.bind(c,"")))}}else{if(d=$(t),"string"==typeof d)for(d=d.toLowerCase();p[f[1]+d];)k();f=[f,d,null],b++,!y&&i[d]&&(y=b),l[d]&&(u=d)}}),u)for(f[0]||r(`Wrong close tag \`${u}\``),k();n!==u&&p[n];)k();h=o+t.length,y||(e=e.replace(/\s*\n\s*|\s*\n\s*/g,"").replace(/\s+/g," ")),e&&$((n=0,e),f,!0)}),f[0]&&p[f[1]]&&k(),b&&r(`Unclosed \`${f[1]}\`.`),f.length<3?f[1]:(f.shift(),f)}const r=t=>{throw SyntaxError(t)},l=o.empty={},p=o.close={},i=o.pre={};"area base br col command embed hr img input keygen link meta param source track wbr ! !doctype ? ?xml".split(" ").map(t=>o.empty[t]=!0);let s={li:"",dt:"dd",dd:"dt",p:"address article aside blockquote details div dl fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol pre section table",rt:"rp",rp:"rt",optgroup:"",option:"optgroup",caption:"tbody thead tfoot tr colgroup",colgroup:"thead tbody tfoot tr caption",thead:"tbody tfoot caption",tbody:"tfoot caption",tfoot:"caption",tr:"tbody tfoot",td:"th tr",th:"td tr tbody"};for(let t in s)for(let e of[...s[t].split(" "),t])o.close[t]=o.close[t+e]=!0;"pre textarea".split(" ").map(t=>o.pre[t]=!0);
		const xhtm = o;

		ioi.xhtm = function(type, props, ...children) {
			var elCleanned = {
				tag: '',
				id: '',
				events: [],
				class: [],
				style: [],
				other: [],
				single: [],
			}

			elCleanned.tag = ioi.isArr(type) ? type.join('') : type;

			if (elCleanned.tag.indexOf('.') > -1) {
				elCleanned.class = elCleanned.tag.split('.');
				elCleanned.tag = elCleanned.class.splice(0, 1)[0];
			}
			if (elCleanned.tag.indexOf('#') > -1) {
				elCleanned.id = elCleanned.tag.split('#');
				elCleanned.tag = elCleanned.id.splice(0, 1)[0];
				elCleanned.id = elCleanned.id[0];
			}

			if (elCleanned.tag === 'if') {
				if (props === null || props === undefined || props === {} || props === []) throw SyntaxError('<if> tag must have a condition');

				children = ioi.flattenArr(children);

				// If condition is false, find the 'ELSE' node or return empty
				if (ioi.hop(props, 'false')) {
					if (children.length) {
						for (var c of children) {
							if (c.tagName === 'ELSE') return Array.prototype.slice.call(c.childNodes);
						}
					}

					return [];
				}

				// If condition is true, find the 'THEN' node or return current node childrens
				if (children.length) {
					for (var c of children) {
						if (c.tagName === 'THEN') return Array.prototype.slice.call(c.childNodes);
					}
				}

				return children;
			}

			// ioi`<div><header><p>toto</p><button>ata</button></header><content>qsdsqd</content></div>`.appendAfter('a', 0)
			// ioi`<div innerHTML="aaaa"><if ${true}><then><span innerHTML="ddd"></span><span innerHTML="eee"></span></then><else><span innerHTML="uuu"></span></else></if></div><div innerHTML="bbbb"></div>`.appendTo('body')
			// ioi`<style>div{color:#fff;background-color:#f00}</style><div innerHTML="aaaa"></div>`.prependTo('body')
			// ioi`<input style="${{color:'#fff', 'background-color':"#f00"}}" .aaa .${['bbb', 'ccc']} .${'ddd'}${'eeee'} ?${['hhh', 'iii']}=${true}/>`[0]
			// var sd='a',sdf;ioi`<input truea trueb=true truec="true" ${'test'}=${true} !${'testf'}=${false} !${'testx'}=${true} sd=${sd} !sdi=${sd} sdf=${sdf} !sdfi=${sdf} testa="${true} bb">`[0]

			if (props) {
				var propName = '';

				for (var p in props) {
					propName = p.replace(/^@/g, 'on').replace(/^[#!\?\.]/g, '').replace(/,+/g, ',').replace(/^,|[^\w\d],|,$/g, '');

					if (propName !== 'null' && propName !== 'undefined') {
						if (/^\?/g.test(p)) { // show attribute only if value is truthy, hide if falsy
							if (ioi.isTruthy(props[p])) {
								elCleanned.single.push(propName.replace(/,/g, ' '));
							}
						} else if (/^\!/g.test(p) && (ioi.isFalsy(props[p]) || props[p] === true)) { // show attribute=value if value is truthy ("true" and "false" as text), hide if falsy
							if (props[p] === true) elCleanned.other.push(propName + '="true"');
							else if (props[p] === false) elCleanned.other.push(propName + '="false"');
						} else if (/^#/g.test(p)) { // id short hand
							if (!ioi.isEmpty(propName)) {
								elCleanned.id = propName;
							}
						} else if (/^\./g.test(p)) { // class short hand
							if (!ioi.isEmpty(propName)) {
								if (ioi.isStr(propName)) elCleanned.class.push(propName.replace(/\./g, ' '));
								else elCleanned.class.push(propName);
							}
						} else if (propName === 'id') {
							if (!ioi.isEmpty(props[p])) {
								elCleanned.id = ioi.isArr(props[p]) ? props[p].join('') : props[p];
							}
						} else if (propName === 'class') {
							if (!ioi.isEmpty(props[p] )) {
								if (ioi.isArr(props[p]) && props[p].indexOf('') > -1) elCleanned.class.push(props[p].join(''));
								else elCleanned.class.push(props[p]);
							}
						} else if (propName === 'style') {
							if (ioi.isPureObj(props[p])) {
								elCleanned.style.push(...Object.entries(props[p]).map(([k, v]) => k+':'+v));
							} else {
								elCleanned.style.push(props[p]);
							}
						} else if (/^(on|@)\w+/gmi.test(p) && typeof props[p] === 'function') {
							elCleanned.events.push(p);
						} else if (p === 'innerHTML') { // Special 'innerHTML' attribute : Don't show attribute, attribute will be used as content if children is empty
						} else if (p === 'if') { // Special 'if' attribute : if attribute value is truthy then keep going, else directly exit and return nothing
							console.log(p, props[p], ioi.isTruthy(props[p]), ioi.isFalsy(props[p]))
							if (ioi.isFalsy(props[p])) {
								return [];
							}
						} else if (props[p] === false) { // Don't show attribute
						} else if (props[p] === true) {
							elCleanned.single.push(propName);
						} else {
							elCleanned.other.push(propName + '="' + (ioi.isArr(props[p]) ? props[p].join('') : props[p]) + '"');
							// console.error('ioi.xhtm: unsupported attribute or value "' + propName + '" => \'' + p + '\'=', props[p]);
						}
					}
				}
			}

			var d = '<' + elCleanned.tag;
			if (!ioi.isEmpty(elCleanned.id)) d += ` id="${elCleanned.id}"`;
			if (elCleanned.class.length > 0) d += ` class="${ioi.flattenArgFull(elCleanned.class).join(' ').replace(/\s+/g, ' ').trim()}"`;
			if (elCleanned.other.length > 0) d += ' ' + elCleanned.other.join(' ');
			if (elCleanned.single.length > 0) d += ' ' + elCleanned.single.join(' ');
			if (elCleanned.style.length > 0) d += ` style="${elCleanned.style.join(';')}"`;
			d += '></' + elCleanned.tag + '>';

			d = ioi(d, 0);
			for (var ev of elCleanned.events) d.on(ev.replace(/^on|@|\!/gmi, ''), props[ev]);
			
			children = ioi.flattenArr(children);

			if (children.length) {
				for (var c of children) {
					if (c.tagName === 'STYLE' && ioi.isStr(c.attr('scoped'))) {
						ioi.css.scoped(c.innerText)(d);
					} else {
						d.append(c);
					}
				}
			} else if (props && ioi.hop(props, 'innerHTML')) {
				d.append(ioi`${props.innerHTML}`);
			}
			
			return d;
		};

		// ioi.lit = ioi.htm = xhtm.bind(ioi.xhtm);
		ioi.lit = ioi.htm = function() {
			if (!/^\s*</.test(arguments[0][0])) return ioi.text.apply(this, arguments);

			var out = xhtm.apply(ioi.xhtm, arguments);

			// console.log(out)
			if (ioi.isStr(out)) return out;

			out = ioi.flattenArr(out);

			if (out.length === 1) return ioi(out, 0);
			return ioi(out);
		};
			
		// ioi.lit.css = function (_parts, ..._vars) {
		// ioi.lit.css = ioi.lit.text = ioi.text = function (_parts, ..._vars) {
		ioi.lit.css = ioi.lit.text = ioi.text = ioi.css = function (_parts, ..._vars) {
			var res = _parts[0];
			for (var i = 1; i < _parts.length; i++) res += _vars[i-1] + _parts[i];
			return res;
		};
	
		ioi.hasProp = ioi.hasOwn = ioi.hop = (_obj, ..._args) => {
			var args = [], a;
	
			if(ioi.isStr(_obj)) {
				_args.unshift(_obj);
				_obj = ioi;
			} else if (_obj instanceof Array) {
				_args = _args.concat(_obj);
				_obj = ioi;
			}
	
			if(_args.length === 1 && ioi.isStr(_args[0])) {
				if(_args[0] in _obj) return true;
	
				if (_args[0].indexOf(',') > -1 || _args[0].indexOf(' ') > -1) {
					_args = _args[0].replace(/[\s]/g, ',').replace(/,+/g, ',').split(',');
					for(var i = 0; i < _args.length; i++) {
						if(!(_args[i] in _obj)) return false;
					}
	
					return true;
				}
				
				return _args[0] in _obj;
			}
			
			if(_args.length > 0) {
				for(var i = 0; i < _args.length; i++) {
					if(ioi.isStr(_args[i])) {
						if (_args[i].indexOf(',') > -1 || _args[i].indexOf(' ') > -1) {
							args = args.concat(_args[i].replace(/[\s]/g, ',').replace(/,+/g, ',').split(','));
						} else {
							args.unshift(_args[i]);
						}
					} else if (_args[i] instanceof Array) {
						args = args.concat(_args[i]);
					}
				}
			}
	
			if(args.length === 1) return args[0] in _obj;
	
			for(var i = 0; i < args.length; i++) {
				if(!(_args[i] in _obj)) return false;
			}
	
			return true;
		};
	
		ioi.crypto = ioi.hash = (str, seed = 0) => {
			let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
			for (let i = 0, ch; i < str.length; i++) {
				ch = str.charCodeAt(i);
				h1 = Math.imul(h1 ^ ch, 2654435761);
				h2 = Math.imul(h2 ^ ch, 1597334677);
			}
			
			h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
			h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
			
			return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36);
		};

		ioi.crypto.hash = (_str) => {
			var hash = 0, chr;
			
			if (_str.length === 0) return hash;
	
			for (var i = 0; i < _str.length; i++) {
				chr = _str.charCodeAt(i);
				hash = ((hash << 5) - hash) + chr;
				hash |= 0; // Convert to 32bit integer
			}
			
			return hash.toString(36);
		};
	
		ioi.crypto.cyrb53 = (str, seed = 0) => {
			let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
			for (let i = 0, ch; i < str.length; i++) {
				ch = str.charCodeAt(i);
				h1 = Math.imul(h1 ^ ch, 2654435761);
				h2 = Math.imul(h2 ^ ch, 1597334677);
			}
			
			h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
			h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
			
			return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36);
		};
	
		
	
		ioi.getSelector = function (_node, _previousSelector = '', _computeIndex = true) {
			if (ioi.isNode(this) && !ioi.isNode(_node)) return ioi.getSelector(this, _node, !(_previousSelector === false));
			if (!ioi.isStr(_previousSelector)) _previousSelector = '';
	
			var selector = ioi.getSelectorInParent(_node, _previousSelector, _computeIndex);
	
			if(ioi.isSelectorUnique(selector, _node.ownerDocument)) return selector;
	
			if (_node.parentNode.id !== '') {
				return `#${_node.parentNode.id.replace(/(\:|\.)/gmi, '\\$1')} > ${selector}`;
			} else if (_node.closest('[id]:not([id=""])')) {
				var parentID = `#${_node.closest('[id]:not([id=""])').id.replace(/(\:|\.)/gmi, '\\$1')} `;
				if(ioi.isSelectorUnique(parentID + selector, _node.ownerDocument)) return parentID + selector;
			}
	
			return ioi.getSelector(_node.parentNode, ' > ' + selector, _computeIndex);
		}
		
		ioi.getSelectorInParent = function (_node, _previousSelector = '', _computeIndex = true) {
			if (ioi.isNode(this) && !ioi.isNode(_node)) return ioi.getSelector(this, _node, !(_previousSelector === false));
			if (!ioi.isStr(_previousSelector)) _previousSelector = '';
	
			// If node has an ID then assume it is unique
			if (_node.id !== '') return '#' + _node.id.replace(/(\:|\.)/gmi, '\\$1') + _previousSelector;
	
			var tag = _node.tagName.toLowerCase(); // node.localName

			// If node tagname is 'body' then assume it is unique
			if (tag === 'body') return tag + _previousSelector;

			// Get node index position in parent
			var index = '';
			if (_computeIndex !== false && _node.parentNode.children.length > 1) {
				index = ioi.nodeIndex(_node) + 1;
				
				if (index === 1) index = ':first-child';
				else if (index === _node.parentNode.children.length) index = ':last-child';
				else index = ':nth-child(' + index + ')';
			}
	
			// Check all class
			var classCurrent = '';
			var classCompiled = '';
			var classUnique = '';
			var classFirst = '';
			var classLonguest = '';
			var classSecondLonguest = '';
			for (var c of _node.classList) {
				classCurrent = '.' + c.replace(/(\:|\.)/gmi, '\\$1');
				if (ioi.isSelectorUniqueInParent(classCurrent, _node.parentNode)) {
					classUnique = classCurrent;
					break;
				} else if (ioi.isSelectorUniqueInParent(tag + classCurrent, _node.parentNode)) {
					classUnique = classCurrent;
					break;
				} else if (classCurrent.length > classLonguest.length) {
					classLonguest = classCurrent;
					classSecondLonguest = classLonguest;
					if (ioi.isSelectorUniqueInParent(classLonguest + classSecondLonguest, _node.parentNode)) {
						classUnique = classLonguest + classSecondLonguest;
						break;
					} else if (ioi.isSelectorUniqueInParent(tag + classLonguest + classSecondLonguest, _node.parentNode)) {
						classUnique = classLonguest + classSecondLonguest;
						break;
					}
				}
	
				if (classFirst === '') {
					classFirst = classCurrent;
				}
	
				classCompiled += classCurrent;
	
				if (ioi.isSelectorUniqueInParent(classCompiled, _node.parentNode)) {
					classUnique = classCompiled;
					break;
				}
			}
	
			if (classUnique !== '') {
				if (ioi.isSelectorUniqueInParent(classUnique, _node.parentNode)) return classUnique + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(tag + classCurrent, _node.parentNode)) return tag + classUnique + _previousSelector;
			}
	
			if (ioi.isSelectorUniqueInParent(tag, _node.parentNode)) return tag + _previousSelector;
			
			if (classFirst !== '') {
				if (ioi.isSelectorUniqueInParent(classFirst + index, _node.parentNode)) return classFirst + index + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(classLonguest + index, _node.parentNode)) return classLonguest + index + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(tag + classFirst + index, _node.parentNode)) return tag + classFirst + index + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(tag + classLonguest + index, _node.parentNode)) return tag + classLonguest + index + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(classLonguest + classSecondLonguest + index, _node.parentNode)) return classLonguest + classSecondLonguest + index + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(tag + classLonguest + classSecondLonguest + index, _node.parentNode)) return tag + classLonguest + classSecondLonguest + index + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(classCompiled, _node.parentNode)) return classUnique + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(tag + classCompiled, _node.parentNode)) return tag + classUnique + _previousSelector;
				else if (ioi.isSelectorUniqueInParent(tag + classCompiled + index, _node.parentNode)) return tag + classUnique + index + _previousSelector;
			}
	
			if (ioi.isSelectorUniqueInParent(tag + index, _node.parentNode)) return tag + index + _previousSelector;
			
	
	
			var selector = '';
	
			for (var c of _node.classList) {
				selector += '.' + c.replace(/(\:|\.)/gmi, '\\$1');
				if(ioi.isSelectorUniqueInParent(selector, _node.parentNode)) return selector + _previousSelector;
				else if(ioi.isSelectorUniqueInParent(tag + selector, _node.parentNode)) return tag + selector + _previousSelector;
				else if(ioi.isSelectorUniqueInParent(tag + selector + index, _node.parentNode)) return tag + selector + index + _previousSelector;
			}
	
			selector = tag + selector;
	
			var attributes = _node.attributes;
			var attrCompiled = '';
			var attrValCompiled = '';
			var attrUnique = '';
			var attrValUnique = '';
			for(var i = 0; i < attributes.length; i++) {
				if(SELECTOR_IGNORE_ATTRIBUTE.indexOf(attributes[i].name) === -1) {
					attrCompiled += `[${attributes[i].name}]`;
					if(ioi.isSelectorUniqueInParent(selector + attrCompiled, _node.parentNode)) {
						attrUnique = attrCompiled;
						break;
					}
					attrValCompiled += `[${attributes[i].name}="${attributes[i].value}"]`;
					if(ioi.isSelectorUniqueInParent(selector + attrValCompiled, _node.parentNode) && attrValUnique === '') {
						attrValUnique = attrValCompiled;
					}
				}
			}
			selector += attrUnique || attrValUnique || attrValCompiled;
			if(ioi.isSelectorUniqueInParent(selector, _node.parentNode)) return selector + _previousSelector;
	
			// #ioi-window-6 .ioi-window-header-title
			// #ioi-window-6 > .ioi-window-header > .flex-1
	
			// span.ioi-window-header-title.flex-1
			// span.ioi-window-header-title.flex-1:nth-child(1)
			// div#ioi-window-6 > div.ioi-window-header.relative.flex.flex-center.p-6.pw-8.ioi-window-handle:nth-child(1) > span.ioi-window-header-title.flex-1:nth-child(1)
	
			return selector + index + _previousSelector;
			// return ioi.getSelector(_node.parentNode, _computeIndex) + ' > ' + selector;
		}
	
		ioi.getSelectorOld = function (_node, _computeIndex = true) {
			if (ioi.isNode(this) && !ioi.isNode(_node)) return ioi.getSelector(this, !(_node === false));
	
			var selector = _node.tagName.toLowerCase(); // node.localName

			if (selector === 'body') return selector;
	
			if(_node.id && _node.id !== '') return selector + '#' + _node.id.replace(/(\:|\.)/gmi, '\\$1');
	
			selector += _node.className ? '.' + _node.className.replace(/(\:|\.)/gmi, '\\$1').split(' ').join('.') : '';
	
			if(ioi.isSelectorUnique(selector, _node.ownerDocument)) return selector;
	
			var attributes = _node.attributes;
			for(var i = 0; i < attributes.length; i++) {
				if(SELECTOR_IGNORE_ATTRIBUTE.indexOf(attributes[i].name) === -1) {
					selector += '[' + attributes[i].name + (attributes[i].value !== '' ? '="' + attributes[i].value + '"' : '') + ']';
				}
			}
			// #ioi-window-6 .ioi-window-header-title
			// #ioi-window-6 > .ioi-window-header > .flex-1
			// div#ioi-window-6 > div.ioi-window-header.relative.flex.flex-center.p-6.pw-8.ioi-window-handle:nth-child(1) > span.ioi-window-header-title.flex-1:nth-child(1)
	
			if(ioi.isSelectorUnique(selector, _node.ownerDocument)) return selector;
			
			if (_computeIndex !== false && _node.parentNode.children.length > 1) {
				selector += ':nth-child(' + (ioi.nodeIndex(_node) + 1) + ')';
	
				if(ioi.isSelectorUnique(selector, _node.ownerDocument)) return selector;
			}
	
			return ioi.getSelector(_node.parentNode, _computeIndex) + ' > ' + selector;
		}
	
		ioi.getPath = function (_node, _computeIndex = false) {
			if (ioi.isNode(this) && !ioi.isNode(_node)) return ioi.getPath(this, _node === true);
	
			var selector = _node.tagName.toLowerCase(); // node.localName
	
			selector += _node.id ? '#' + _node.id.replace(/(\:|\.)/gmi, '\\$1') : '';
	
			selector += _node.className ? '.' + _node.className.split(' ').join('.') : '';
	
			var attributes = _node.attributes;
			for(var i = 0; i < attributes.length; i++) {
				if(SELECTOR_IGNORE_ATTRIBUTE.indexOf(attributes[i].name) === -1) {
					selector += '[' + attributes[i].name + (attributes[i].value !== '' ? '="' + attributes[i].value + '"' : '') + ']';
				}
			}
			
			if (_computeIndex === true && _node.parentNode.children.length > 1) {
				selector += ':nth-child(' + (ioi.nodeIndex(_node) + 1) + ')';
			}
	
			return _node.parentNode.nodeType !== Node.DOCUMENT_NODE ? ioi.getPath(_node.parentNode, _computeIndex) + ' > ' + selector : selector;
		}
	
		ioi.addStyle = (_url) => {
			if(ioi('link[href="' + _url + '"]').length === 0) {
				var el = document.createElement('link');
				el.rel = 'stylesheet';
				el.type = 'text/css';
				el.href = _url;
				// el.crossorigin = 'anonymous';
				// el.media = 'all';
				// el.media = 'screen,print';
	
				el.onerror = (err) => {
					console.error('ioi.addStyle : "' + _url + '" has returned an error !');
				}
				el.onload = () => {
					// console.log('file loaded !');
				}
				
				document.head.appendChild(el);
			}
		};
	
		ioi.addScript = (_url, _type) => {
			if(ioi('script[src="' + _url + '"]').length === 0) {
				var el = document.createElement('script');
				if(['json', '.json'].indexOf(_type) > -1) {
					el.type = 'application/json';
				} else {
					el.type = 'application/javascript';
				}
				el.src = _url;
				// el.crossorigin = 'anonymous';
				// el.defer = 'defer';
	
	
				el.onerror = (err) => {
					console.error('ioi.addScript : "' + _url + '" has returned an error !');
				}
				el.onload = () => {
					// console.log('file loaded !');
				}
	
				document.body.appendChild(el);
			}
		};

		ioi.isOffline = () => {
			// TODO : https://github.com/lukeed/is-offline
		};
	
		// window.performance
		// window.performance.memory // chrome only - ram usage
		// navigator.hardwareConcurrency // nb of logical processors
		// worker
	
		/*
		let workerList = [];
	
		for (let i = 0; i < window.navigator.hardwareConcurrency; i++) {
		let newWorker = {
			worker: new Worker("cpuworker.js"),
			inUse: false,
		};
		workerList.push(newWorker);
		}
		 */
	
	
	
	
	
		function doEach(_callback, _return = false, _reversed = false) {
			return function (..._args) {
				if (this.length === 0) return this;

				if(ioi.isStr(_callback)) {
					if(/^ioi./i.test(_callback) && ioi.hop(_callback.replace(/^ioi./i, ''))) {
						_callback = ioi[_callback.replace(/^ioi./i, '')];
					} else if(document[_callback]) {
						_callback = document[_callback];
					} else {
						console.error('ioi.doEach : "' + _callback + '" is not a property of document !');
						return this;
					}

					if(!ioi.isFn(_callback)) {
						console.error('ioi.doEach : first arg must be a string or a function', _callback);
						return this;
					}
				}
	
				var results = [];
	
				if (this.length > 1 && !ioi.isNode(this)) {
					var hasResults = false;
					if (_reversed) {
						for (var i = this.length - 1; i >= 0; i--) {
							results.push(_callback.apply(ioi(this[i], 0), _args.length > 0 ? _args : [this[i], i, this]));
							if(results[i] !== undefined) hasResults = true;
						}
					} else {
						for (var i = 0; i < this.length; i++) {
							results.push(_callback.apply(ioi(this[i], 0), _args.length > 0 ? _args : [this[i], i, this]));
							if(results[i] !== undefined) hasResults = true;
						}
					}
					return _return && hasResults ? results : this;
				}
	
				results = _callback.apply(this.first(), _args.length > 0 ? _args : [this.first(), 0, this]);
	
				return _return && results !== undefined ? results : this;
			};
		}

		ioi.testa = function(a, b, c) {
			console.log(this, arguments);
			console.log(this, a, b, c);
		};

		// function tagAll(e) {
		// 	if (!e) { return; }
		// 	e.QinsQ = true;
		// 	e = e.firstChild;
		// 	for (; e; e = e.nextSibling) {
		// 		if (e !== undefined && e.nodeType === 1) tagAll(e);
		// 	}
		// }

		ioi.setAttrRecusive = (_node, _key, _value) => {
			if (!_node) { return; }
			_node.setAttribute(_key, _value);
			_node = _node.firstChild;
			for (; _node; _node = _node.nextSibling) {
				if (_node !== undefined && _node.nodeType === 1) ioi.setAttrRecusive(_node, _key, _value);
			}
		};

		ioi.attr = function (_node, _key, _value = null, _recursive = false) {
			if (ioi.isNode(this)) return ioi.attr(this, _node, _key, _value);

			if (_value !== null) {
				if (_recursive) {
					console.warn('rec')
					return ioi.setAttrRecusive(_node, _key, _value);
				}
				_node.setAttribute(_key, _value);

				return _node;
			}
			return _node.getAttribute(_key);
		};

		ioi.setPropRecusive = (_node, _key, _value) => {
			if (!_node) { return; }
			_node[_key] = _value;
			_node = _node.firstChild;
			for (; _node; _node = _node.nextSibling) {
				if (_node !== undefined && _node.nodeType === 1) ioi.setPropRecusive(_node, _key, _value);
			}
		};

		ioi.prop = function (_node, _key, _value = null, _recursive = false) {
			if (ioi.isNode(this)) return ioi.prop(this, _node, _key, _value);

			if (_value !== null) {
				if (_recursive) {
					return ioi.setPropRecusive(_node, _key, _value);
				}
				_node[_key] = _value;

				return _node;
			}
			return _node[_key];
		};
	
		ioi.fn = {
			ioiExtended: true,
			extend: function (_target) {
				if (_target.ioiExtended === true) return _target; // eOnly extend target once

				for (var i in ioi.fn) {
					if (ioi.fn.hasOwnProperty(i)) {
						_target[i] = ioi.fn[i];
					}
				}
				return _target;
			},
			first: function () { return ioi(this, 0); },
			last: function () { return ioi(this[this.length - 1], 0); },
			prev: function () { return ioi(this.first().previousSibling, 0); },
			next: function () { return ioi(this.first().nextSibling, 0); },
			at: function (_i) { return ioi(this, _i); },
			css: doEach('ioi.css', true),
			index: doEach(ioi.nodeIndex, true),
			test: doEach('ioi.testa'),
			remove: doEach(function () { this.parentNode.removeChild(this); }),
			selector: doEach(ioi.getSelector, true),
			path: doEach(ioi.getPath, true),
			find: doEach(function (_arg1, _arg2) { return ioi((/\s*>/gmi.test(_arg1) ? ':scope ' : '') + _arg1, this.first(), _arg2); }, true),
			hop: doEach(function (..._args) { _args.unshift(this); return ioi.hop.apply(null, _args); }, true),
			class: doEach(function (_class) { return this.className = ioi.isStr(_class) ? _class : this.className; }, true),
			hasClass: doEach(function (_class) { return this.classList.contains(_class); }, true),
			addClass: doEach(function (_class) { this.classList.add(_class); }),
			toggleClass: doEach(function (_class) { console.error('//todo') }),
			removeClass: doEach(function (_class) { this.classList.remove(_class); }),
			toggleShow: doEach(function() { this.css('display') === 'none' ? this.show() : this.hide(); }),
			show: doEach(function() { this.css('display', ''); }),
			hide: doEach(function() { this.css('display', 'none'); }),
			cssClear: doEach(function() { this.attr('style', ''); }),
			html: doEach(function(_str) { if (ioi.isStr(_str)) { this.innerHTML = _str; return this; } return this.innerHTML; }, true),
			val: doEach(function (_value = null) { if (_value !== null) { this.value = _value; return this; } return this.value; }, true),
			attr: doEach('ioi.attr', true),
			// attr: doEach(function (_key, _value = null) { if (_value !== null) { this.setAttribute(_key, _value); return this; } return this.getAttribute(_key); }, true),
			removeAttr: doEach(function (_key) { this.removeAttribute(_key); return this; }, true),
			prop: doEach('ioi.prop', true),
			// prop: doEach(function (_key, _value = null) { if (_value !== null) { this[_key] = _value; return this; } return this[_key]; }, true),
			off: doEach('removeEventListener'),
			on: doEach(function (_type, _selector, _callback, _opts) {
				if (ioi.isStr(_type)) _type = _type.replace(/\s*,+\s*|\s+/gmi, ' ').split(' ');
	
				if (ioi.isFn(_selector)) {
					for(var i = 0; i < _type.length; i++) {
						this.addEventListener(_type[i], _selector, _callback);
					}
				} else {
					for(var i = 0; i < _type.length; i++) {
						this.addEventListener(_type[i], function (e) {
							if(_selector === null) {
								_callback.apply(this, e);
							} else if(_selector && e.target.closest(_selector)) {
								_callback.apply(e.target.closest(_selector), e);
							}
						}, _opts);
					}
				}
			}),
			is: doEach(function (_selector) {
				if (ioi.isStr(_selector)) _selector = ioi(_selector, this.ownerDocument);
				
				if (ioi.isNode(_selector)) return node === this;
				else if (ioi.isNodeList(_selector)) {
					for (var node of nodeList) {
						if (node === this) return true;
					}
				}

				return false
			}, true),
			each: function(_callback) {
				if (!ioi.isFn(_callback)) {
					console.error('ioi.each : first arg must be a function');
					return false;
				}
	
				if (this.length > 0 && ioi.isArr(this)) {
					for (var i = 0; i < this.length; i++) {
						// console.log(this)
						// console.log(this[i])
						_callback.apply(ioi(this[i], 0), [this[i], i, this]);
					}
				} else {
					_callback.apply(this, [this, 0, this]);
				}
	
				return this;
			},
			parent: doEach(function (_arg1) {
				if (this.parentNode === null) return this; 
				else if (ioi.isNum(_arg1)) { return this.parents(_arg1).at(_arg1); }
	
				return ioi(ioi.isStr(_arg1) ? this.closest(_arg1) : this.parentNode, 0);
			}, true),
			parents: doEach(function (_maxCount = -1) {
				var parentList = [];
				var node = this;
				var count = 0;
				if (!ioi.isNum(_maxCount)) _maxCount = -1;

				while (node = node.parentNode) {
					parentList.push(node);
					count++;
					if (_maxCount > -1 && count > _maxCount) break;
				}

				return ioi(parentList);
			}, true),
			prepend: doEach(function (_node) {
				if (ioi.isHTMLString(_node)) _node = ioi(_node);
				
				if (ioi.isNodeList(_node)) {
					// for(var n of _node) this.insertBefore(n, this.firstChild);
					for (var i = _node.length - 1; i >= 0; i--) {
						this.insertBefore(_node[i], this.firstChild);
					}
					return true;
				}
	
				this.insertBefore(_node, this.firstChild);
	
				return true;
			}),
			append: doEach(function (_node) {
				if (ioi.isHTMLString(_node)) _node = ioi(_node);

				if (ioi.isNodeList(_node)) {
					for(var n of _node) this.appendChild(n);
					return true;
				}
				
				if (ioi.isStr(_node)) {
					this.appendChild(this.ownerDocument.createTextNode(_node));
					return true;
				}
	
				this.appendChild(_node);
	
				return true;
			}),
			prependTo: doEach(function (_node, _pos) {
				if (this === _node) {
					if (this.tagName === 'STYLE') _node = ioi('head');
					else _node = ioi('body');
				}
				if (ioi.isStr(_node)) _node = ioi(_node, this.ownerDocument, _pos);
	
				if (ioi.isNodeList(_node)) {
					for(var n of _node) n.insertBefore(this, n.firstChild);
					return true;
				}
	
				_node.insertBefore(this, _node.firstChild);
	
				return true;
			}, false, true),
			appendTo: doEach(function (_node = 'body', _pos) {
				if (this === _node) {
					if (this.tagName === 'STYLE') _node = ioi('head');
					else _node = ioi('body');
				}
				if (this === _node) _node = ioi('body');
				if (ioi.isStr(_node)) _node = ioi(_node, this.ownerDocument, _pos);
				
				if (ioi.isNodeList(_node)) {
					for(var n of _node) n.appendChild(this);
					return true;
				}
	
				_node.appendChild(this);
	
				return true;
			}),
			appendBefore: doEach(function (_node, _pos) {
				if (ioi.isStr(_node)) _node = ioi(_node, this.ownerDocument, _pos);
				
				if (ioi.isNodeList(_node)) {
					for(var n of _node) n.parentNode.insertBefore(this, n);
					return true;
				}
	
				_node.parentNode.insertBefore(this, _node);
	
				return true;
			}),
			appendAfter: doEach(function (_node, _pos) {
				if (ioi.isStr(_node)) _node = ioi(_node, this.ownerDocument, _pos);
				
				if (ioi.isNodeList(_node)) {
					for(var n of _node) n.parentNode.insertBefore(this, n.nextSibling);
					return true;
				}
	
				_node.parentNode.insertBefore(this, _node.nextSibling);
	
				return true;
			}, false, true)
		};
	
		//#region Init IOI
		default_return = ioi.fn.extend(default_return);
		//#endregion  Init IOI
	
		return ioi;
	}();

	if (window._ === undefined) {
		_ = window._ = ioi;
	}
	if (window.$ === undefined) {
		$ = window.$ = ioi;
	}
}

ioi(() => {
	ioi.isReady = true;

	ioi.require('more');
	
	if (/required?|module/gmi.test(ioi.scriptPath)) {
		ioi.require(decodeURIComponent(ioi.scriptPath.replace(/^.*ioi\.js\??|#.*$/gmi, '').replace(/^.*((required?|module)=([^&]*)).*$/gmi, '$3')));
	}

	if (/styles?|css/gmi.test(ioi.scriptPath)) {
		var required_styles = decodeURIComponent(ioi.scriptPath.replace(/^.*ioi\.js\??|#.*$/gmi, '').replace(/^.*((styles?|css)=([^&]*)).*$/gmi, '$3'));

		if (required_styles === 'all') {
			required_styles = [ioi.scriptRootPath + 'short-styles.css', ioi.scriptRootPath + 'color-styles.css', ]
			for(var style of required_styles) {
				ioi.addStyle(style);
			}
		} else {
			if (ioi.isStr(required_styles)) required_styles = required_styles.replace(/\s*,+\s*|\s+/gmi, ' ').split(' ');
			required_styles = required_styles.filter(x => x);

			for(var style of required_styles) {
				ioi.addStyle(style);
			}
		}
	}

});