From 7a40eaf7da15224c43f30e8ed099880b1d3649ca Mon Sep 17 00:00:00 2001
From: SkyratBot <59378654+SkyratBot@users.noreply.github.com>
Date: Wed, 29 Nov 2023 00:09:49 +0100
Subject: [PATCH] [MIRROR] Drops ie8 support [MDB IGNORE] (#25322)

* Drops ie8 support (#79974)

<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

We currently transpile TGUI down into ie8. This was primarily for Linux
compatibility, which, to my understanding, hasn't worked for quite some
time. As we approach 2024, consider that ie8 is nearly 15 years old and
had its support ended in 2016. I believe sunsetting ie8 is in order.

>I have no objections to remove IE8 support and fully target IE11.

https://github.com/tgstation/tgstation/issues/79943#issuecomment-1826735705_

<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! -->

- Probably improves performance to some degree, you're only as slow as
your weakest link.
- Reduced maintenance burden
<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. -->

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and it's effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

N/A if they can even see this message it doesn't affect them

<!-- Both :cl:'s are required for the changelog to work! You can put
your name to the right of the first :cl: if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->

* Drops ie8 support

---------

Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com>
---
 tgui/package.json                           |   2 +-
 tgui/packages/tgui-bench/package.json       |   2 +-
 tgui/packages/tgui-dev-server/package.json  |   2 +-
 tgui/packages/tgui-polyfill/00-html5shiv.js | 331 -------
 tgui/packages/tgui-polyfill/01-ie8.js       | 837 -----------------
 tgui/packages/tgui-polyfill/02-dom4.js      | 973 --------------------
 tgui/packages/tgui-polyfill/03-css-om.js    |  45 -
 tgui/packages/tgui-polyfill/1-misc.js       |  53 ++
 tgui/packages/tgui-polyfill/10-misc.js      |  62 --
 tgui/packages/tgui-polyfill/package.json    |   4 +-
 tgui/packages/tgui/package.json             |   2 +-
 tgui/public/tgui-polyfill.min.js            |   2 +-
 tgui/public/tgui.html                       |   1 -
 tgui/tsconfig.json                          |   2 +-
 tgui/webpack.config.js                      |   9 +-
 15 files changed, 68 insertions(+), 2259 deletions(-)
 delete mode 100644 tgui/packages/tgui-polyfill/00-html5shiv.js
 delete mode 100644 tgui/packages/tgui-polyfill/01-ie8.js
 delete mode 100644 tgui/packages/tgui-polyfill/02-dom4.js
 delete mode 100644 tgui/packages/tgui-polyfill/03-css-om.js
 create mode 100644 tgui/packages/tgui-polyfill/1-misc.js
 delete mode 100644 tgui/packages/tgui-polyfill/10-misc.js

diff --git a/tgui/package.json b/tgui/package.json
index c42971992b5..6197fa10901 100644
--- a/tgui/package.json
+++ b/tgui/package.json
@@ -1,7 +1,7 @@
 {
   "private": true,
   "name": "tgui-workspace",
-  "version": "4.3.2",
+  "version": "4.4.0",
   "packageManager": "yarn@3.3.1",
   "workspaces": [
     "packages/*"
diff --git a/tgui/packages/tgui-bench/package.json b/tgui/packages/tgui-bench/package.json
index 5ebd81685ea..22719711733 100644
--- a/tgui/packages/tgui-bench/package.json
+++ b/tgui/packages/tgui-bench/package.json
@@ -1,7 +1,7 @@
 {
   "private": true,
   "name": "tgui-bench",
-  "version": "4.3.2",
+  "version": "4.4.0",
   "dependencies": {
     "@fastify/static": "^6.12.0",
     "common": "workspace:*",
diff --git a/tgui/packages/tgui-dev-server/package.json b/tgui/packages/tgui-dev-server/package.json
index 7327b07ddb0..a5b8ee12f73 100644
--- a/tgui/packages/tgui-dev-server/package.json
+++ b/tgui/packages/tgui-dev-server/package.json
@@ -1,7 +1,7 @@
 {
   "private": true,
   "name": "tgui-dev-server",
-  "version": "4.3.2",
+  "version": "4.4.0",
   "type": "module",
   "dependencies": {
     "axios": "^1.6.2",
diff --git a/tgui/packages/tgui-polyfill/00-html5shiv.js b/tgui/packages/tgui-polyfill/00-html5shiv.js
deleted file mode 100644
index ce4b97576fa..00000000000
--- a/tgui/packages/tgui-polyfill/00-html5shiv.js
+++ /dev/null
@@ -1,331 +0,0 @@
-/**
- * @file
- * @copyright 2014 Alexander Farkas
- * @license MIT
- */
-
-/* eslint-disable */
-// prettier-ignore
-(function(window, document) {
-/*jshint evil:true */
-  /** version */
-  var version = '3.7.3';
-
-  /** Preset options */
-  var options = window.html5 || {};
-
-  /** Used to skip problem elements */
-  var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
-
-  /** Not all elements can be cloned in IE **/
-  var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
-
-  /** Detect whether the browser supports default html5 styles */
-  var supportsHtml5Styles;
-
-  /** Name of the expando, to work with multiple documents or to re-shiv one document */
-  var expando = '_html5shiv';
-
-  /** The id for the the documents expando */
-  var expanID = 0;
-
-  /** Cached data for each document */
-  var expandoData = {};
-
-  /** Detect whether the browser supports unknown elements */
-  var supportsUnknownElements;
-
-  (function() {
-    try {
-        var a = document.createElement('a');
-        a.innerHTML = '<xyz></xyz>';
-        //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
-        supportsHtml5Styles = ('hidden' in a);
-
-        supportsUnknownElements = a.childNodes.length == 1 || (function() {
-          // assign a false positive if unable to shiv
-          (document.createElement)('a');
-          var frag = document.createDocumentFragment();
-          return (
-            typeof frag.cloneNode == 'undefined' ||
-            typeof frag.createDocumentFragment == 'undefined' ||
-            typeof frag.createElement == 'undefined'
-          );
-        }());
-    } catch(e) {
-      // assign a false positive if detection fails => unable to shiv
-      supportsHtml5Styles = true;
-      supportsUnknownElements = true;
-    }
-
-  }());
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Creates a style sheet with the given CSS text and adds it to the document.
-   * @private
-   * @param {Document} ownerDocument The document.
-   * @param {String} cssText The CSS text.
-   * @returns {StyleSheet} The style element.
-   */
-  function addStyleSheet(ownerDocument, cssText) {
-    var p = ownerDocument.createElement('p'),
-        parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
-
-    p.innerHTML = 'x<style>' + cssText + '</style>';
-    return parent.insertBefore(p.lastChild, parent.firstChild);
-  }
-
-  /**
-   * Returns the value of `html5.elements` as an array.
-   * @private
-   * @returns {Array} An array of shived element node names.
-   */
-  function getElements() {
-    var elements = html5.elements;
-    return typeof elements == 'string' ? elements.split(' ') : elements;
-  }
-
-  /**
-   * Extends the built-in list of html5 elements
-   * @memberOf html5
-   * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
-   * @param {Document} ownerDocument The context document.
-   */
-  function addElements(newElements, ownerDocument) {
-    var elements = html5.elements;
-    if(typeof elements != 'string'){
-      elements = elements.join(' ');
-    }
-    if(typeof newElements != 'string'){
-      newElements = newElements.join(' ');
-    }
-    html5.elements = elements +' '+ newElements;
-    shivDocument(ownerDocument);
-  }
-
-   /**
-   * Returns the data associated to the given document
-   * @private
-   * @param {Document} ownerDocument The document.
-   * @returns {Object} An object of data.
-   */
-  function getExpandoData(ownerDocument) {
-    var data = expandoData[ownerDocument[expando]];
-    if (!data) {
-        data = {};
-        expanID++;
-        ownerDocument[expando] = expanID;
-        expandoData[expanID] = data;
-    }
-    return data;
-  }
-
-  /**
-   * returns a shived element for the given nodeName and document
-   * @memberOf html5
-   * @param {String} nodeName name of the element
-   * @param {Document|DocumentFragment} ownerDocument The context document.
-   * @returns {Object} The shived element.
-   */
-  function createElement(nodeName, ownerDocument, data){
-    if (!ownerDocument) {
-        ownerDocument = document;
-    }
-    if(supportsUnknownElements){
-        return ownerDocument.createElement(nodeName);
-    }
-    if (!data) {
-        data = getExpandoData(ownerDocument);
-    }
-    var node;
-
-    if (data.cache[nodeName]) {
-        node = data.cache[nodeName].cloneNode();
-    } else if (saveClones.test(nodeName)) {
-        node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
-    } else {
-        node = data.createElem(nodeName);
-    }
-
-    // Avoid adding some elements to fragments in IE < 9 because
-    // * Attributes like `name` or `type` cannot be set/changed once an element
-    //   is inserted into a document/fragment
-    // * Link elements with `src` attributes that are inaccessible, as with
-    //   a 403 response, will cause the tab/window to crash
-    // * Script elements appended to fragments will execute when their `src`
-    //   or `text` property is set
-    return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
-  }
-
-  /**
-   * returns a shived DocumentFragment for the given document
-   * @memberOf html5
-   * @param {Document} ownerDocument The context document.
-   * @returns {Object} The shived DocumentFragment.
-   */
-  function createDocumentFragment(ownerDocument, data){
-    if (!ownerDocument) {
-        ownerDocument = document;
-    }
-    if(supportsUnknownElements){
-        return ownerDocument.createDocumentFragment();
-    }
-    data = data || getExpandoData(ownerDocument);
-    var clone = data.frag.cloneNode(),
-        i = 0,
-        elems = getElements(),
-        l = elems.length;
-    for(;i<l;i++){
-        clone.createElement(elems[i]);
-    }
-    return clone;
-  }
-
-  /**
-   * Shivs the `createElement` and `createDocumentFragment` methods of the document.
-   * @private
-   * @param {Document|DocumentFragment} ownerDocument The document.
-   * @param {Object} data of the document.
-   */
-  function shivMethods(ownerDocument, data) {
-    if (!data.cache) {
-        data.cache = {};
-        data.createElem = ownerDocument.createElement;
-        data.createFrag = ownerDocument.createDocumentFragment;
-        data.frag = data.createFrag();
-    }
-
-
-    ownerDocument.createElement = function(nodeName) {
-      //abort shiv
-      if (!html5.shivMethods) {
-          return data.createElem(nodeName);
-      }
-      return createElement(nodeName, ownerDocument, data);
-    };
-
-    ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
-      'var n=f.cloneNode(),c=n.createElement;' +
-      'h.shivMethods&&(' +
-        // unroll the `createElement` calls
-        getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
-          data.createElem(nodeName);
-          data.frag.createElement(nodeName);
-          return 'c("' + nodeName + '")';
-        }) +
-      ');return n}'
-    )(html5, data.frag);
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Shivs the given document.
-   * @memberOf html5
-   * @param {Document} ownerDocument The document to shiv.
-   * @returns {Document} The shived document.
-   */
-  function shivDocument(ownerDocument) {
-    if (!ownerDocument) {
-        ownerDocument = document;
-    }
-    var data = getExpandoData(ownerDocument);
-
-    if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
-      data.hasCSS = !!addStyleSheet(ownerDocument,
-        // corrects block display not defined in IE6/7/8/9
-        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
-        // adds styling not present in IE6/7/8/9
-        'mark{background:#FF0;color:#000}' +
-        // hides non-rendered elements
-        'template{display:none}'
-      );
-    }
-    if (!supportsUnknownElements) {
-      shivMethods(ownerDocument, data);
-    }
-    return ownerDocument;
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * The `html5` object is exposed so that more elements can be shived and
-   * existing shiving can be detected on iframes.
-   * @type Object
-   * @example
-   *
-   * // options can be changed before the script is included
-   * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
-   */
-  var html5 = {
-
-    /**
-     * An array or space separated string of node names of the elements to shiv.
-     * @memberOf html5
-     * @type Array|String
-     */
-    'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
-
-    /**
-     * current version of html5shiv
-     */
-    'version': version,
-
-    /**
-     * A flag to indicate that the HTML5 style sheet should be inserted.
-     * @memberOf html5
-     * @type Boolean
-     */
-    'shivCSS': (options.shivCSS !== false),
-
-    /**
-     * Is equal to true if a browser supports creating unknown/HTML5 elements
-     * @memberOf html5
-     * @type boolean
-     */
-    'supportsUnknownElements': supportsUnknownElements,
-
-    /**
-     * A flag to indicate that the document's `createElement` and `createDocumentFragment`
-     * methods should be overwritten.
-     * @memberOf html5
-     * @type Boolean
-     */
-    'shivMethods': (options.shivMethods !== false),
-
-    /**
-     * A string to describe the type of `html5` object ("default" or "default print").
-     * @memberOf html5
-     * @type String
-     */
-    'type': 'default',
-
-    // shivs the document according to the specified `html5` object options
-    'shivDocument': shivDocument,
-
-    //creates a shived element
-    createElement: createElement,
-
-    //creates a shived documentFragment
-    createDocumentFragment: createDocumentFragment,
-
-    //extends list of elements
-    addElements: addElements
-  };
-
-  /*--------------------------------------------------------------------------*/
-
-  // expose html5
-  window.html5 = html5;
-
-  // shiv the document
-  shivDocument(document);
-
-  if(typeof module == 'object' && module.exports){
-    module.exports = html5;
-  }
-
-}(window, document));
diff --git a/tgui/packages/tgui-polyfill/01-ie8.js b/tgui/packages/tgui-polyfill/01-ie8.js
deleted file mode 100644
index cebb677bccf..00000000000
--- a/tgui/packages/tgui-polyfill/01-ie8.js
+++ /dev/null
@@ -1,837 +0,0 @@
-/**
- * @file
- * @copyright 2013 Andrea Giammarchi, WebReflection
- * @license MIT
- */
-
-/* eslint-disable */
-// prettier-ignore
-(function(window){
-  /*! (C) WebReflection Mit Style License */
-  if (document.createEvent) return;
-  var
-    DUNNOABOUTDOMLOADED = true,
-    READYEVENTDISPATCHED = false,
-    ONREADYSTATECHANGE = 'onreadystatechange',
-    DOMCONTENTLOADED = 'DOMContentLoaded',
-    SECRET = '__IE8__' + Math.random(),
-    // Object = window.Object,
-    defineProperty = Object.defineProperty ||
-    // just in case ...
-    function (object, property, descriptor) {
-      object[property] = descriptor.value;
-    },
-    defineProperties = Object.defineProperties ||
-    // IE8 implemented defineProperty but not the plural...
-    function (object, descriptors) {
-      for(var key in descriptors) {
-        if (hasOwnProperty.call(descriptors, key)) {
-          try {
-            defineProperty(object, key, descriptors[key]);
-          } catch(o_O) {
-            if (window.console) {
-              console.log(key + ' failed on object:', object, o_O.message);
-            }
-          }
-        }
-      }
-    },
-    getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor,
-    hasOwnProperty = Object.prototype.hasOwnProperty,
-    // here IE7 will break like a charm
-    ElementPrototype = window.Element.prototype,
-    TextPrototype = window.Text.prototype,
-    // none of above native constructors exist/are exposed
-    possiblyNativeEvent = /^[a-z]+$/,
-    // ^ actually could probably be just /^[a-z]+$/
-    readyStateOK = /loaded|complete/,
-    types = {},
-    div = document.createElement('div'),
-    html = document.documentElement,
-    removeAttribute = html.removeAttribute,
-    setAttribute = html.setAttribute,
-    valueDesc = function (value) {
-      return {
-        enumerable: true,
-        writable: true,
-        configurable: true,
-        value: value
-      };
-    }
-  ;
-
-  function commonEventLoop(currentTarget, e, $handlers, synthetic) {
-    for(var
-      handler,
-      continuePropagation,
-      handlers = $handlers.slice(),
-      evt = enrich(e, currentTarget),
-      i = 0, length = handlers.length; i < length; i++
-    ) {
-      handler = handlers[i];
-      if (typeof handler === 'object') {
-        if (typeof handler.handleEvent === 'function') {
-          handler.handleEvent(evt);
-        }
-      } else {
-        handler.call(currentTarget, evt);
-      }
-      if (evt.stoppedImmediatePropagation) break;
-    }
-    continuePropagation = !evt.stoppedPropagation;
-    /*
-    if (continuePropagation && !synthetic && !live(currentTarget)) {
-      evt.cancelBubble = true;
-    }
-    */
-    return (
-      synthetic &&
-      continuePropagation &&
-      currentTarget.parentNode
-    ) ?
-      currentTarget.parentNode.dispatchEvent(evt) :
-      !evt.defaultPrevented
-    ;
-  }
-
-  function commonDescriptor(get, set) {
-    return {
-      // if you try with enumerable: true
-      // IE8 will miserably fail
-      configurable: true,
-      get: get,
-      set: set
-    };
-  }
-
-  function commonTextContent(protoDest, protoSource, property) {
-    var descriptor = getOwnPropertyDescriptor(
-      protoSource || protoDest, property
-    );
-    defineProperty(
-      protoDest,
-      'textContent',
-      commonDescriptor(
-        function () {
-          return descriptor.get.call(this);
-        },
-        function (textContent) {
-          descriptor.set.call(this, textContent);
-        }
-      )
-    );
-  }
-
-  function enrich(e, currentTarget) {
-    e.currentTarget = currentTarget;
-    e.eventPhase = (
-      // AT_TARGET : BUBBLING_PHASE
-      e.target === e.currentTarget ? 2 : 3
-    );
-    return e;
-  }
-
-  function find(array, value) {
-    var i = array.length;
-    while(i-- && array[i] !== value);
-    return i;
-  }
-
-  function getTextContent() {
-    if (this.tagName === 'BR') return '\n';
-    var
-      textNode = this.firstChild,
-      arrayContent = []
-    ;
-    while(textNode) {
-      if (textNode.nodeType !== 8 && textNode.nodeType !== 7) {
-        arrayContent.push(textNode.textContent);
-      }
-      textNode = textNode.nextSibling;
-    }
-    return arrayContent.join('');
-  }
-
-  function live(self) {
-    return self.nodeType !== 9 && html.contains(self);
-  }
-
-  function onkeyup(e) {
-    var evt = document.createEvent('Event');
-    evt.initEvent('input', true, true);
-    (e.srcElement || e.fromElement || document).dispatchEvent(evt);
-  }
-
-  function onReadyState(e) {
-    if (!READYEVENTDISPATCHED && readyStateOK.test(
-      document.readyState
-    )) {
-      READYEVENTDISPATCHED = !READYEVENTDISPATCHED;
-      document.detachEvent(ONREADYSTATECHANGE, onReadyState);
-      e = document.createEvent('Event');
-      e.initEvent(DOMCONTENTLOADED, true, true);
-      document.dispatchEvent(e);
-    }
-  }
-
-  function getter(attr) {
-    return function() {
-      return html[attr] || (document.body && document.body[attr]) || 0;
-    };
-  }
-
-  function setTextContent(textContent) {
-    var node;
-    while ((node = this.lastChild)) {
-      this.removeChild(node);
-    }
-    /*jshint eqnull:true */
-    if (textContent != null) {
-      this.appendChild(document.createTextNode(textContent));
-    }
-  }
-
-  function verify(self, e) {
-    if (!e) {
-      e = window.event;
-    }
-    if (!e.target) {
-      e.target = e.srcElement || e.fromElement || document;
-    }
-    if (!e.timeStamp) {
-      e.timeStamp = (new Date()).getTime();
-    }
-    return e;
-  }
-
-  // normalized textContent for:
-  //  comment, script, style, text, title
-  commonTextContent(
-    window.HTMLCommentElement.prototype,
-    ElementPrototype,
-    'nodeValue'
-  );
-
-  commonTextContent(
-    window.HTMLScriptElement.prototype,
-    null,
-    'text'
-  );
-
-  commonTextContent(
-    TextPrototype,
-    null,
-    'nodeValue'
-  );
-
-  commonTextContent(
-    window.HTMLTitleElement.prototype,
-    null,
-    'text'
-  );
-
-  defineProperty(
-    window.HTMLStyleElement.prototype,
-    'textContent',
-    (function(descriptor){
-      return commonDescriptor(
-        function () {
-          return descriptor.get.call(this.styleSheet);
-        },
-        function (textContent) {
-          descriptor.set.call(this.styleSheet, textContent);
-        }
-      );
-    }(getOwnPropertyDescriptor(window.CSSStyleSheet.prototype, 'cssText')))
-  );
-
-  var opacityre = /\b\s*alpha\s*\(\s*opacity\s*=\s*(\d+)\s*\)/;
-  defineProperty(
-    window.CSSStyleDeclaration.prototype,
-    'opacity', {
-      get: function() {
-        var m = this.filter.match(opacityre);
-        return m ? (m[1] / 100).toString() : '';
-      },
-      set: function(value) {
-        this.zoom = 1;
-        var found = false;
-        if (value < 1) {
-          value = ' alpha(opacity=' + Math.round(value * 100) + ')';
-        }
-        else {
-          value = '';
-        }
-        this.filter = this.filter.replace(opacityre,
-                        function() { found = true; return value; });
-        if (!found && value) {
-          this.filter += value;
-        }
-      }
-    }
-  );
-
-  defineProperties(
-    ElementPrototype,
-    {
-      // bonus
-      textContent: {
-        get: getTextContent,
-        set: setTextContent
-      },
-      // http://www.w3.org/TR/ElementTraversal/#interface-elementTraversal
-      firstElementChild: {
-        get: function () {
-          for(var
-            childNodes = this.childNodes || [],
-            i = 0, length = childNodes.length;
-            i < length; i++
-          ) {
-            if (childNodes[i].nodeType == 1) return childNodes[i];
-          }
-        }
-      },
-      lastElementChild: {
-        get: function () {
-          for(var
-            childNodes = this.childNodes || [],
-            i = childNodes.length;
-            i--;
-          ) {
-            if (childNodes[i].nodeType == 1) return childNodes[i];
-          }
-        }
-      },
-      oninput: {
-        get: function () {
-          return this._oninput || null;
-        },
-        set: function (oninput) {
-          if (this._oninput) {
-            this.removeEventListener('input', this._oninput);
-            this._oninput = oninput;
-            if (oninput) {
-              this.addEventListener('input', oninput);
-            }
-          }
-        }
-      },
-      previousElementSibling: {
-        get: function () {
-          var previousElementSibling = this.previousSibling;
-          while (previousElementSibling && previousElementSibling.nodeType != 1) {
-            previousElementSibling = previousElementSibling.previousSibling;
-          }
-          return previousElementSibling;
-        }
-      },
-      nextElementSibling: {
-        get: function () {
-          var nextElementSibling = this.nextSibling;
-          while (nextElementSibling && nextElementSibling.nodeType != 1) {
-            nextElementSibling = nextElementSibling.nextSibling;
-          }
-          return nextElementSibling;
-        }
-      },
-      childElementCount: {
-        get: function () {
-          for(var
-            count = 0,
-            childNodes = this.childNodes || [],
-            i = childNodes.length; i--; count += childNodes[i].nodeType == 1
-          );
-          return count;
-        }
-      },
-      /*
-      // children would be an override
-      // IE8 already supports them but with comments too
-      // not just nodeType 1
-      children: {
-        get: function () {
-          for(var
-            children = [],
-            childNodes = this.childNodes || [],
-            i = 0, length = childNodes.length;
-            i < length; i++
-          ) {
-            if (childNodes[i].nodeType == 1) {
-              children.push(childNodes[i]);
-            }
-          }
-          return children;
-        }
-      },
-      */
-      // DOM Level 2 EventTarget methods and events
-      addEventListener: valueDesc(function (type, handler, capture) {
-        if (typeof handler !== 'function' && typeof handler !== 'object') return;
-        var
-          self = this,
-          ontype = 'on' + type,
-          temple = self[SECRET] ||
-                      defineProperty(
-                        self, SECRET, {value: {}}
-                      )[SECRET],
-          currentType = temple[ontype] || (temple[ontype] = {}),
-          handlers  = currentType.h || (currentType.h = []),
-          e, attr
-        ;
-        if (!hasOwnProperty.call(currentType, 'w')) {
-          currentType.w = function (e) {
-            // e[SECRET] is a silent notification needed to avoid
-            // fired events during live test
-            return e[SECRET] || commonEventLoop(self, verify(self, e), handlers, false);
-          };
-          // if not detected yet
-          if (!hasOwnProperty.call(types, ontype)) {
-            // and potentially a native event
-            if(possiblyNativeEvent.test(type)) {
-              // do this heavy thing
-              try {
-                // TODO:  should I consider tagName too so that
-                //        INPUT[ontype] could be different ?
-                e = document.createEventObject();
-                // do not clone ever a node
-                // specially a document one ...
-                // use the secret to ignore them all
-                e[SECRET] = true;
-                // document a part if a node has never been
-                // added to any other node, fireEvent might
-                // behave very weirdly (read: trigger unspecified errors)
-                if (self.nodeType != 9) {
-                  /*jshint eqnull:true */
-                  if (self.parentNode == null) {
-                    div.appendChild(self);
-                  }
-                  if ((attr = self.getAttribute(ontype))) {
-                    removeAttribute.call(self, ontype);
-                  }
-                }
-                self.fireEvent(ontype, e);
-                types[ontype] = true;
-              } catch(meh) {
-                types[ontype] = false;
-                while (div.hasChildNodes()) {
-                  div.removeChild(div.firstChild);
-                }
-              }
-              if (attr != null) {
-                setAttribute.call(self, ontype, attr);
-              }
-            } else {
-              // no need to bother since
-              // 'x-event' ain't native for sure
-              types[ontype] = false;
-            }
-          }
-          if ((currentType.n = types[ontype])) {
-            self.attachEvent(ontype, currentType.w);
-          }
-        }
-        if (find(handlers, handler) < 0) {
-          handlers[capture ? 'unshift' : 'push'](handler);
-        }
-        if (type === 'input') {
-          self.attachEvent('onkeyup', onkeyup);
-        }
-      }),
-      dispatchEvent: valueDesc(function (e) {
-        var
-          self = this,
-          ontype = 'on' + e.type,
-          temple = self[SECRET],
-          currentType = temple && temple[ontype],
-          valid = !!currentType,
-          parentNode
-        ;
-        if (!e.target) e.target = self;
-        return (valid ? (
-          currentType.n /* && live(self) */ ?
-            self.fireEvent(ontype, e) :
-            commonEventLoop(
-              self,
-              e,
-              currentType.h,
-              true
-            )
-        ) : (
-          (parentNode = self.parentNode) /* && live(self) */ ?
-            parentNode.dispatchEvent(e) :
-            true
-        )), !e.defaultPrevented;
-      }),
-      removeEventListener: valueDesc(function (type, handler, capture) {
-        if (typeof handler !== 'function' && typeof handler !== 'object') return;
-        var
-          self = this,
-          ontype = 'on' + type,
-          temple = self[SECRET],
-          currentType = temple && temple[ontype],
-          handlers = currentType && currentType.h,
-          i = handlers ? find(handlers, handler) : -1
-        ;
-        if (-1 < i) handlers.splice(i, 1);
-      })
-    }
-  );
-
-  /* this is not needed in IE8
-  defineProperties(window.HTMLSelectElement.prototype, {
-    value: {
-      get: function () {
-        return this.options[this.selectedIndex].value;
-      }
-    }
-  });
-  //*/
-
-  // EventTarget methods for Text nodes too
-  defineProperties(TextPrototype, {
-    addEventListener: valueDesc(ElementPrototype.addEventListener),
-    dispatchEvent: valueDesc(ElementPrototype.dispatchEvent),
-    removeEventListener: valueDesc(ElementPrototype.removeEventListener)
-  });
-
-  defineProperties(
-    window.XMLHttpRequest.prototype,
-    {
-      addEventListener: valueDesc(function (type, handler, capture) {
-        var
-          self = this,
-          ontype = 'on' + type,
-          temple = self[SECRET] ||
-                      defineProperty(
-                        self, SECRET, {value: {}}
-                      )[SECRET],
-          currentType = temple[ontype] || (temple[ontype] = {}),
-          handlers  = currentType.h || (currentType.h = [])
-        ;
-        if (find(handlers, handler) < 0) {
-          if (!self[ontype]) {
-            self[ontype] = function () {
-              var e = document.createEvent('Event');
-              e.initEvent(type, true, true);
-              self.dispatchEvent(e);
-            };
-          }
-          handlers[capture ? 'unshift' : 'push'](handler);
-        }
-      }),
-      dispatchEvent: valueDesc(function (e) {
-        var
-          self = this,
-          ontype = 'on' + e.type,
-          temple = self[SECRET],
-          currentType = temple && temple[ontype],
-          valid = !!currentType
-        ;
-        return valid && (
-          currentType.n /* && live(self) */ ?
-            self.fireEvent(ontype, e) :
-            commonEventLoop(
-              self,
-              e,
-              currentType.h,
-              true
-            )
-        );
-      }),
-      removeEventListener: valueDesc(ElementPrototype.removeEventListener)
-    }
-  );
-
-  var buttonGetter = getOwnPropertyDescriptor(Event.prototype, 'button').get;
-  defineProperties(
-    window.Event.prototype,
-    {
-      bubbles: valueDesc(true),
-      cancelable: valueDesc(true),
-      preventDefault: valueDesc(function () {
-        if (this.cancelable) {
-          this.returnValue = false;
-        }
-      }),
-      stopPropagation: valueDesc(function () {
-        this.stoppedPropagation = true;
-        this.cancelBubble = true;
-      }),
-      stopImmediatePropagation: valueDesc(function () {
-        this.stoppedImmediatePropagation = true;
-        this.stopPropagation();
-      }),
-      initEvent: valueDesc(function(type, bubbles, cancelable){
-        this.type = type;
-        this.bubbles = !!bubbles;
-        this.cancelable = !!cancelable;
-        if (!this.bubbles) {
-          this.stopPropagation();
-        }
-      }),
-      pageX: {get: function(){ return this._pageX || (this._pageX = this.clientX + window.scrollX - (html.clientLeft || 0)); }},
-      pageY: {get: function(){ return this._pageY || (this._pageY = this.clientY + window.scrollY - (html.clientTop || 0)); }},
-      which: {get: function(){ return this.keyCode ? this.keyCode : (isNaN(this.button) ? undefined : this.button + 1); }},
-      charCode: {get: function(){ return (this.keyCode && this.type == 'keypress') ? this.keyCode : 0; }},
-      buttons: {get: function(){ return buttonGetter.call(this); }},
-      button: {get: function() {
-        var buttons = this.buttons;
-        return (buttons & 1 ? 0 : (buttons & 2 ? 2 : (buttons & 4 ? 1 : undefined)));
-      }},
-      defaultPrevented: {get: function() {
-        // if preventDefault() was never called, or returnValue not given a value
-        // then returnValue is undefined
-        var returnValue = this.returnValue, undef;
-        return !(returnValue === undef || returnValue);
-      }},
-      relatedTarget: {get: function() {
-        var type = this.type;
-        if (type === 'mouseover') {
-          return this.fromElement;
-        } else if (type === 'mouseout') {
-          return this.toElement;
-        } else {
-          return null;
-        }
-      }}
-    }
-  );
-
-  defineProperties(
-    window.HTMLDocument.prototype,
-    {
-      defaultView: {
-        get: function () {
-          return this.parentWindow;
-        }
-      },
-      textContent: {
-        get: function () {
-          return this.nodeType === 11 ? getTextContent.call(this) : null;
-        },
-        set: function (textContent) {
-          if (this.nodeType === 11) {
-            setTextContent.call(this, textContent);
-          }
-        }
-      },
-      addEventListener: valueDesc(function(type, handler, capture) {
-        var self = this;
-        ElementPrototype.addEventListener.call(self, type, handler, capture);
-        // NOTE:  it won't fire if already loaded, this is NOT a $.ready() shim!
-        //        this behaves just like standard browsers
-        if (
-          DUNNOABOUTDOMLOADED &&
-          type === DOMCONTENTLOADED &&
-          !readyStateOK.test(
-            self.readyState
-          )
-        ) {
-          DUNNOABOUTDOMLOADED = false;
-          self.attachEvent(ONREADYSTATECHANGE, onReadyState);
-          /* global top */
-          if (window == top) {
-            (function gonna(e){try{
-              self.documentElement.doScroll('left');
-              onReadyState();
-              }catch(o_O){
-              setTimeout(gonna, 50);
-            }}());
-          }
-        }
-      }),
-      dispatchEvent: valueDesc(ElementPrototype.dispatchEvent),
-      removeEventListener: valueDesc(ElementPrototype.removeEventListener),
-      createEvent: valueDesc(function(Class){
-        var e;
-        if (Class !== 'Event') throw new Error('unsupported ' + Class);
-        e = document.createEventObject();
-        e.timeStamp = (new Date()).getTime();
-        return e;
-      })
-    }
-  );
-
-  defineProperties(
-    window.Window.prototype,
-    {
-      getComputedStyle: valueDesc(function(){
-
-        var // partially grabbed from jQuery and Dean's hack
-          notpixel = /^(?:[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/,
-          position = /^(top|right|bottom|left)$/,
-          re = /\-([a-z])/g,
-          place = function (match, $1) {
-            return $1.toUpperCase();
-          }
-        ;
-
-        function ComputedStyle(_) {
-          this._ = _;
-        }
-
-        ComputedStyle.prototype.getPropertyValue = function (name) {
-          var
-            el = this._,
-            style = el.style,
-            currentStyle = el.currentStyle,
-            runtimeStyle = el.runtimeStyle,
-            result,
-            left,
-            rtLeft
-          ;
-          if (name == 'opacity') {
-            return style.opacity || '1';
-          }
-          name = (name === 'float' ? 'style-float' : name).replace(re, place);
-          result = currentStyle ? currentStyle[name] : style[name];
-          if (notpixel.test(result) && !position.test(name)) {
-            left = style.left;
-            rtLeft = runtimeStyle && runtimeStyle.left;
-            if (rtLeft) {
-              runtimeStyle.left = currentStyle.left;
-            }
-            style.left = name === 'fontSize' ? '1em' : result;
-            result = style.pixelLeft + 'px';
-            style.left = left;
-            if (rtLeft) {
-              runtimeStyle.left = rtLeft;
-            }
-          }
-          /*jshint eqnull:true */
-          return result == null ?
-            result : ((result + '') || 'auto');
-        };
-
-        // unsupported
-        function PseudoComputedStyle() {}
-        PseudoComputedStyle.prototype.getPropertyValue = function () {
-          return null;
-        };
-
-        return function (el, pseudo) {
-          return pseudo ?
-            new PseudoComputedStyle(el) :
-            new ComputedStyle(el);
-        };
-
-      }()),
-
-      addEventListener: valueDesc(function (type, handler, capture) {
-        var
-          self = window,
-          ontype = 'on' + type,
-          handlers
-        ;
-        if (!self[ontype]) {
-          self[ontype] = function(e) {
-            return commonEventLoop(self, verify(self, e), handlers, false) && undefined;
-          };
-        }
-        handlers = self[ontype][SECRET] || (
-          self[ontype][SECRET] = []
-        );
-        if (find(handlers, handler) < 0) {
-          handlers[capture ? 'unshift' : 'push'](handler);
-        }
-      }),
-      dispatchEvent: valueDesc(function (e) {
-        var method = window['on' + e.type];
-        return method ? method.call(window, e) !== false && !e.defaultPrevented : true;
-      }),
-      removeEventListener: valueDesc(function (type, handler, capture) {
-        var
-          ontype = 'on' + type,
-          handlers = (window[ontype] || Object)[SECRET],
-          i = handlers ? find(handlers, handler) : -1
-         ;
-        if (-1 < i) handlers.splice(i, 1);
-      }),
-      pageXOffset: {get: getter('scrollLeft')},
-      pageYOffset: {get: getter('scrollTop')},
-      scrollX: {get: getter('scrollLeft')},
-      scrollY: {get: getter('scrollTop')},
-      innerWidth: {get: getter('clientWidth')},
-      innerHeight: {get: getter('clientHeight')}
-    }
-  );
-
-  window.HTMLElement = window.Element;
-
-  (function (styleSheets, HTML5Element, i) {
-    for (i = 0; i < HTML5Element.length; i++) document.createElement(HTML5Element[i]);
-    if (!styleSheets.length) document.createStyleSheet('');
-    styleSheets[0].addRule(HTML5Element.join(','), 'display:block;');
-  }(document.styleSheets, ['header', 'nav', 'section', 'article', 'aside', 'footer']));
-
-  (function () {
-    if (document.createRange) return;
-    document.createRange = function createRange() {
-      return new Range();
-    };
-
-    function getContents(start, end) {
-      var nodes = [start];
-      while (start !== end) {
-        nodes.push(start = start.nextSibling);
-      }
-      return nodes;
-    }
-
-    function Range() {}
-    var proto = Range.prototype;
-    proto.cloneContents = function cloneContents() {
-      for (var
-        fragment = this._start.ownerDocument.createDocumentFragment(),
-        nodes = getContents(this._start, this._end),
-        i = 0,
-        length = nodes.length;
-        i < length; i++
-      ) {
-        fragment.appendChild(nodes[i].cloneNode(true));
-      }
-      return fragment;
-    };
-    proto.cloneRange = function cloneRange() {
-      var range = new Range();
-      range._start = this._start;
-      range._end = this._end;
-      return range;
-    };
-    proto.deleteContents = function deleteContents() {
-      for (var
-        parentNode = this._start.parentNode,
-        nodes = getContents(this._start, this._end),
-        i = 0,
-        length = nodes.length;
-        i < length; i++
-      ) {
-        parentNode.removeChild(nodes[i]);
-      }
-    };
-    proto.extractContents = function extractContents() {
-      for (var
-        fragment = this._start.ownerDocument.createDocumentFragment(),
-        nodes = getContents(this._start, this._end),
-        i = 0,
-        length = nodes.length;
-        i < length; i++
-      ) {
-        fragment.appendChild(nodes[i]);
-      }
-      return fragment;
-    };
-    proto.setEndAfter = function setEndAfter(node) {
-      this._end = node;
-    };
-    proto.setEndBefore = function setEndBefore(node) {
-      this._end = node.previousSibling;
-    };
-    proto.setStartAfter = function setStartAfter(node) {
-      this._start = node.nextSibling;
-    };
-    proto.setStartBefore = function setStartBefore(node) {
-      this._start = node;
-    };
-  }());
-}(window));
diff --git a/tgui/packages/tgui-polyfill/02-dom4.js b/tgui/packages/tgui-polyfill/02-dom4.js
deleted file mode 100644
index bf5746319c2..00000000000
--- a/tgui/packages/tgui-polyfill/02-dom4.js
+++ /dev/null
@@ -1,973 +0,0 @@
-/**
- * @file
- * @copyright 2013 Andrea Giammarchi, WebReflection
- * @license MIT
- */
-
-/* eslint-disable */
-// prettier-ignore
-(function(window){
-  'use strict';
-  /* jshint loopfunc: true, noempty: false*/
-  // http://www.w3.org/TR/dom/#element
-
-  function createDocumentFragment() {
-    return document.createDocumentFragment();
-  }
-
-  function createElement(nodeName) {
-    return document.createElement(nodeName);
-  }
-
-  function enoughArguments(length, name) {
-    if (!length) throw new Error(
-      'Failed to construct ' +
-        name +
-      ': 1 argument required, but only 0 present.'
-    );
-  }
-
-  function mutationMacro(nodes) {
-    if (nodes.length === 1) {
-      return textNodeIfPrimitive(nodes[0]);
-    }
-    for (var
-      fragment = createDocumentFragment(),
-      list = slice.call(nodes),
-      i = 0; i < nodes.length; i++
-    ) {
-      fragment.appendChild(textNodeIfPrimitive(list[i]));
-    }
-    return fragment;
-  }
-
-  function textNodeIfPrimitive(node) {
-    return typeof node === 'object' ? node : document.createTextNode(node);
-  }
-
-  for(var
-    head,
-    property,
-    TemporaryPrototype,
-    TemporaryTokenList,
-    wrapVerifyToken,
-    document = window.document,
-    hOP = Object.prototype.hasOwnProperty,
-    defineProperty = Object.defineProperty || function (object, property, descriptor) {
-      if (hOP.call(descriptor, 'value')) {
-        object[property] = descriptor.value;
-      } else {
-        if (hOP.call(descriptor, 'get'))
-          object.__defineGetter__(property, descriptor.get);
-        if (hOP.call(descriptor, 'set'))
-          object.__defineSetter__(property, descriptor.set);
-      }
-      return object;
-    },
-    indexOf = [].indexOf || function indexOf(value){
-      var length = this.length;
-      while(length--) {
-        if (this[length] === value) {
-          break;
-        }
-      }
-      return length;
-    },
-    // http://www.w3.org/TR/domcore/#domtokenlist
-    verifyToken = function (token) {
-      if (!token) {
-        throw 'SyntaxError';
-      } else if (spaces.test(token)) {
-        throw 'InvalidCharacterError';
-      }
-      return token;
-    },
-    DOMTokenList = function (node) {
-      var
-        noClassName = typeof node.className === 'undefined',
-        className = noClassName ?
-          (node.getAttribute('class') || '') : node.className,
-        isSVG = noClassName || typeof className === 'object',
-        value = (isSVG ?
-          (noClassName ? className : className.baseVal) :
-          className
-        ).replace(trim, '')
-      ;
-      if (value.length) {
-        properties.push.apply(
-          this,
-          value.split(spaces)
-        );
-      }
-      this._isSVG = isSVG;
-      this._ = node;
-    },
-    classListDescriptor = {
-      get: function get() {
-        return new DOMTokenList(this);
-      },
-      set: function(){}
-    },
-    trim = /^\s+|\s+$/g,
-    spaces = /\s+/,
-    SPACE = '\x20',
-    CLASS_LIST = 'classList',
-    toggle = function toggle(token, force) {
-      if (this.contains(token)) {
-        if (!force) {
-          // force is not true (either false or omitted)
-          this.remove(token);
-        }
-      } else if(force === undefined || force) {
-        force = true;
-        this.add(token);
-      }
-      return !!force;
-    },
-    DocumentFragmentPrototype = window.DocumentFragment && DocumentFragment.prototype,
-    Node = window.Node,
-    NodePrototype = (Node || Element).prototype,
-    CharacterData = window.CharacterData || Node,
-    CharacterDataPrototype = CharacterData && CharacterData.prototype,
-    DocumentType = window.DocumentType,
-    DocumentTypePrototype = DocumentType && DocumentType.prototype,
-    ElementPrototype = (window.Element || Node || window.HTMLElement).prototype,
-    HTMLSelectElement = window.HTMLSelectElement || createElement('select').constructor,
-    selectRemove = HTMLSelectElement.prototype.remove,
-    SVGElement = window.SVGElement,
-    properties = [
-      'matches', (
-        ElementPrototype.matchesSelector ||
-        ElementPrototype.webkitMatchesSelector ||
-        ElementPrototype.khtmlMatchesSelector ||
-        ElementPrototype.mozMatchesSelector ||
-        ElementPrototype.msMatchesSelector ||
-        ElementPrototype.oMatchesSelector ||
-        function matches(selector) {
-          var parentNode = this.parentNode;
-          return !!parentNode && -1 < indexOf.call(
-            parentNode.querySelectorAll(selector),
-            this
-          );
-        }
-      ),
-      'closest', function closest(selector) {
-        var parentNode = this, matches;
-        while (
-          // document has no .matches
-          (matches = parentNode && parentNode.matches) &&
-          !parentNode.matches(selector)
-        ) {
-          parentNode = parentNode.parentNode;
-        }
-        return matches ? parentNode : null;
-      },
-      'prepend', function prepend() {
-        var firstChild = this.firstChild,
-            node = mutationMacro(arguments);
-        if (firstChild) {
-          this.insertBefore(node, firstChild);
-        } else {
-          this.appendChild(node);
-        }
-      },
-      'append', function append() {
-        this.appendChild(mutationMacro(arguments));
-      },
-      'before', function before() {
-        var parentNode = this.parentNode;
-        if (parentNode) {
-          parentNode.insertBefore(
-            mutationMacro(arguments), this
-          );
-        }
-      },
-      'after', function after() {
-        var parentNode = this.parentNode,
-            nextSibling = this.nextSibling,
-            node = mutationMacro(arguments);
-        if (parentNode) {
-          if (nextSibling) {
-            parentNode.insertBefore(node, nextSibling);
-          } else {
-            parentNode.appendChild(node);
-          }
-        }
-      },
-      // https://dom.spec.whatwg.org/#dom-element-toggleattribute
-      'toggleAttribute', function toggleAttribute(name, force) {
-        var had = this.hasAttribute(name);
-        if (1 < arguments.length) {
-          if (had && !force)
-            this.removeAttribute(name);
-          else if (force && !had)
-            this.setAttribute(name, "");
-        }
-        else if (had)
-          this.removeAttribute(name);
-        else
-          this.setAttribute(name, "");
-        return this.hasAttribute(name);
-      },
-      // WARNING - DEPRECATED - use .replaceWith() instead
-      'replace', function replace() {
-        this.replaceWith.apply(this, arguments);
-      },
-      'replaceWith', function replaceWith() {
-        var parentNode = this.parentNode;
-        if (parentNode) {
-          parentNode.replaceChild(
-            mutationMacro(arguments),
-            this
-          );
-        }
-      },
-      'remove', function remove() {
-        var parentNode = this.parentNode;
-        if (parentNode) {
-          parentNode.removeChild(this);
-        }
-      }
-    ],
-    slice = properties.slice,
-    i = properties.length; i; i -= 2
-  ) {
-    property = properties[i - 2];
-    if (!(property in ElementPrototype)) {
-      ElementPrototype[property] = properties[i - 1];
-    }
-    // avoid unnecessary re-patch when the script is included
-    // gazillion times without any reason whatsoever
-    // https://github.com/WebReflection/dom4/pull/48
-    if (property === 'remove' && !selectRemove._dom4) {
-      // see https://github.com/WebReflection/dom4/issues/19
-      (HTMLSelectElement.prototype[property] = function () {
-        return 0 < arguments.length ?
-          selectRemove.apply(this, arguments) :
-          ElementPrototype.remove.call(this);
-      })._dom4 = true;
-    }
-    // see https://github.com/WebReflection/dom4/issues/18
-    if (/^(?:before|after|replace|replaceWith|remove)$/.test(property)) {
-      if (CharacterData && !(property in CharacterDataPrototype)) {
-        CharacterDataPrototype[property] = properties[i - 1];
-      }
-      if (DocumentType && !(property in DocumentTypePrototype)) {
-        DocumentTypePrototype[property] = properties[i - 1];
-      }
-    }
-    // see https://github.com/WebReflection/dom4/pull/26
-    if (/^(?:append|prepend)$/.test(property)) {
-      if (DocumentFragmentPrototype) {
-        if (!(property in DocumentFragmentPrototype)) {
-          DocumentFragmentPrototype[property] = properties[i - 1];
-        }
-      } else {
-        try {
-          createDocumentFragment().constructor.prototype[property] = properties[i - 1];
-        } catch(o_O) {}
-      }
-    }
-  }
-
-  // most likely an IE9 only issue
-  // see https://github.com/WebReflection/dom4/issues/6
-  if (!createElement('a').matches('a')) {
-    ElementPrototype[property] = function(matches){
-      return function (selector) {
-        return matches.call(
-          this.parentNode ?
-            this :
-            createDocumentFragment().appendChild(this),
-          selector
-        );
-      };
-    }(ElementPrototype[property]);
-  }
-
-  // used to fix both old webkit and SVG
-  DOMTokenList.prototype = {
-    length: 0,
-    add: function add() {
-      for(var j = 0, token; j < arguments.length; j++) {
-        token = arguments[j];
-        if(!this.contains(token)) {
-          properties.push.call(this, property);
-        }
-      }
-      if (this._isSVG) {
-        this._.setAttribute('class', '' + this);
-      } else {
-        this._.className = '' + this;
-      }
-    },
-    contains: (function(indexOf){
-      return function contains(token) {
-        i = indexOf.call(this, property = verifyToken(token));
-        return -1 < i;
-      };
-    }([].indexOf || function (token) {
-      i = this.length;
-      while(i-- && this[i] !== token){}
-      return i;
-    })),
-    item: function item(i) {
-      return this[i] || null;
-    },
-    remove: function remove() {
-      for(var j = 0, token; j < arguments.length; j++) {
-        token = arguments[j];
-        if(this.contains(token)) {
-          properties.splice.call(this, i, 1);
-        }
-      }
-      if (this._isSVG) {
-        this._.setAttribute('class', '' + this);
-      } else {
-        this._.className = '' + this;
-      }
-    },
-    toggle: toggle,
-    toString: function toString() {
-      return properties.join.call(this, SPACE);
-    }
-  };
-
-  if (SVGElement && !(CLASS_LIST in SVGElement.prototype)) {
-    defineProperty(SVGElement.prototype, CLASS_LIST, classListDescriptor);
-  }
-
-  // http://www.w3.org/TR/dom/#domtokenlist
-  // iOS 5.1 has completely screwed this property
-  // classList in ElementPrototype is false
-  // but it's actually there as getter
-  if (!(CLASS_LIST in document.documentElement)) {
-    defineProperty(ElementPrototype, CLASS_LIST, classListDescriptor);
-  } else {
-    // iOS 5.1 and Nokia ASHA do not support multiple add or remove
-    // trying to detect and fix that in here
-    TemporaryTokenList = createElement('div')[CLASS_LIST];
-    TemporaryTokenList.add('a', 'b', 'a');
-    if ('a\x20b' != TemporaryTokenList) {
-      // no other way to reach original methods in iOS 5.1
-      TemporaryPrototype = TemporaryTokenList.constructor.prototype;
-      if (!('add' in TemporaryPrototype)) {
-        // ASHA double fails in here
-        TemporaryPrototype = window.TemporaryTokenList.prototype;
-      }
-      wrapVerifyToken = function (original) {
-        return function () {
-          var i = 0;
-          while (i < arguments.length) {
-            original.call(this, arguments[i++]);
-          }
-        };
-      };
-      TemporaryPrototype.add = wrapVerifyToken(TemporaryPrototype.add);
-      TemporaryPrototype.remove = wrapVerifyToken(TemporaryPrototype.remove);
-      // toggle is broken too ^_^ ... let's fix it
-      TemporaryPrototype.toggle = toggle;
-    }
-  }
-
-  if (!('contains' in NodePrototype)) {
-    defineProperty(NodePrototype, 'contains', {
-      value: function (el) {
-        while (el && el !== this) el = el.parentNode;
-        return this === el;
-      }
-    });
-  }
-
-  if (!('head' in document)) {
-    defineProperty(document, 'head', {
-      get: function () {
-        return head || (
-          head = document.getElementsByTagName('head')[0]
-        );
-      }
-    });
-  }
-
-  // requestAnimationFrame partial polyfill
-  (function () {
-    for (var
-      raf,
-      rAF = window.requestAnimationFrame,
-      cAF = window.cancelAnimationFrame,
-      prefixes = ['o', 'ms', 'moz', 'webkit'],
-      i = prefixes.length;
-      !cAF && i--;
-    ) {
-      rAF = rAF || window[prefixes[i] + 'RequestAnimationFrame'];
-      cAF = window[prefixes[i] + 'CancelAnimationFrame'] ||
-            window[prefixes[i] + 'CancelRequestAnimationFrame'];
-    }
-    if (!cAF) {
-      // some FF apparently implemented rAF but no cAF
-      if (rAF) {
-        raf = rAF;
-        rAF = function (callback) {
-          var goOn = true;
-          raf(function () {
-            if (goOn) callback.apply(this, arguments);
-          });
-          return function () {
-            goOn = false;
-          };
-        };
-        cAF = function (id) {
-          id();
-        };
-      } else {
-        rAF = function (callback) {
-          return setTimeout(callback, 15, 15);
-        };
-        cAF = function (id) {
-          clearTimeout(id);
-        };
-      }
-    }
-    window.requestAnimationFrame = rAF;
-    window.cancelAnimationFrame = cAF;
-  }());
-
-  // http://www.w3.org/TR/dom/#customevent
-  try{new window.CustomEvent('?');}catch(o_O){
-    window.CustomEvent = function(
-      eventName,
-      defaultInitDict
-    ){
-
-      // the infamous substitute
-      function CustomEvent(type, eventInitDict) {
-        /*jshint eqnull:true */
-        var event = document.createEvent(eventName);
-        if (typeof type != 'string') {
-          throw new Error('An event name must be provided');
-        }
-        if (eventName == 'Event') {
-          event.initCustomEvent = initCustomEvent;
-        }
-        if (eventInitDict == null) {
-          eventInitDict = defaultInitDict;
-        }
-        event.initCustomEvent(
-          type,
-          eventInitDict.bubbles,
-          eventInitDict.cancelable,
-          eventInitDict.detail
-        );
-        return event;
-      }
-
-      // attached at runtime
-      function initCustomEvent(
-        type, bubbles, cancelable, detail
-      ) {
-        /*jshint validthis:true*/
-        this.initEvent(type, bubbles, cancelable);
-        this.detail = detail;
-      }
-
-      // that's it
-      return CustomEvent;
-    }(
-      // is this IE9 or IE10 ?
-      // where CustomEvent is there
-      // but not usable as construtor ?
-      window.CustomEvent ?
-        // use the CustomEvent interface in such case
-        'CustomEvent' : 'Event',
-        // otherwise the common compatible one
-      {
-        bubbles: false,
-        cancelable: false,
-        detail: null
-      }
-    );
-  }
-
-  // window.Event as constructor
-  try { new Event('_'); } catch (o_O) {
-    /* jshint -W022 */
-    o_O = (function ($Event) {
-      function Event(type, init) {
-        enoughArguments(arguments.length, 'Event');
-        var out = document.createEvent('Event');
-        if (!init) init = {};
-        out.initEvent(
-          type,
-          !!init.bubbles,
-          !!init.cancelable
-        );
-        return out;
-      }
-      Event.prototype = $Event.prototype;
-      return Event;
-    }(window.Event || function Event() {}));
-    defineProperty(window, 'Event', {value: o_O});
-    // Android 4 gotcha
-    if (Event !== o_O) Event = o_O;
-  }
-
-  // window.KeyboardEvent as constructor
-  try { new KeyboardEvent('_', {}); } catch (o_O) {
-    /* jshint -W022 */
-    o_O = (function ($KeyboardEvent) {
-      // code inspired by https://gist.github.com/termi/4654819
-      var
-        initType = 0,
-        defaults = {
-          char: '',
-          key: '',
-          location: 0,
-          ctrlKey: false,
-          shiftKey: false,
-          altKey: false,
-          metaKey: false,
-          altGraphKey: false,
-          repeat: false,
-          locale: navigator.language,
-          detail: 0,
-          bubbles: false,
-          cancelable: false,
-          keyCode: 0,
-          charCode: 0,
-          which: 0
-        },
-        eventType
-      ;
-      try {
-        var e = document.createEvent('KeyboardEvent');
-        e.initKeyboardEvent(
-          'keyup', false, false, window, '+', 3,
-          true, false, true, false, false
-        );
-        initType = (
-          (e.keyIdentifier || e.key) == '+' &&
-          (e.keyLocation || e.location) == 3
-        ) && (
-          e.ctrlKey ? e.altKey ? 1 : 3 : e.shiftKey ? 2 : 4
-        ) || 9;
-      } catch(o_O) {}
-      eventType = 0 < initType ? 'KeyboardEvent' : 'Event';
-
-      function getModifier(init) {
-        for (var
-          out = [],
-          keys = [
-            'ctrlKey',
-            'Control',
-            'shiftKey',
-            'Shift',
-            'altKey',
-            'Alt',
-            'metaKey',
-            'Meta',
-            'altGraphKey',
-            'AltGraph'
-          ],
-          i = 0; i < keys.length; i += 2
-        ) {
-          if (init[keys[i]])
-            out.push(keys[i + 1]);
-        }
-        return out.join(' ');
-      }
-
-      function withDefaults(target, source) {
-        for (var key in source) {
-          if (
-            source.hasOwnProperty(key) &&
-            !source.hasOwnProperty.call(target, key)
-          ) target[key] = source[key];
-        }
-        return target;
-      }
-
-      function withInitValues(key, out, init) {
-        try {
-          out[key] = init[key];
-        } catch(o_O) {}
-      }
-
-      function KeyboardEvent(type, init) {
-        enoughArguments(arguments.length, 'KeyboardEvent');
-        init = withDefaults(init || {}, defaults);
-        var
-          out = document.createEvent(eventType),
-          ctrlKey = init.ctrlKey,
-          shiftKey = init.shiftKey,
-          altKey = init.altKey,
-          metaKey = init.metaKey,
-          altGraphKey = init.altGraphKey,
-          modifiers = initType > 3 ? getModifier(init) : null,
-          key = String(init.key),
-          chr = String(init.char),
-          location = init.location,
-          keyCode = init.keyCode || (
-            (init.keyCode = key) &&
-            key.charCodeAt(0)
-          ) || 0,
-          charCode = init.charCode || (
-            (init.charCode = chr) &&
-            chr.charCodeAt(0)
-          ) || 0,
-          bubbles = init.bubbles,
-          cancelable = init.cancelable,
-          repeat = init.repeat,
-          locale = init.locale,
-          view = init.view || window,
-          args
-        ;
-        if (!init.which) init.which = init.keyCode;
-        if ('initKeyEvent' in out) {
-          out.initKeyEvent(
-            type, bubbles, cancelable, view,
-            ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode
-          );
-        } else if (0 < initType && 'initKeyboardEvent' in out) {
-          args = [type, bubbles, cancelable, view];
-          switch (initType) {
-            case 1:
-              args.push(key, location, ctrlKey, shiftKey, altKey, metaKey, altGraphKey);
-              break;
-            case 2:
-              args.push(ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode);
-              break;
-            case 3:
-              args.push(key, location, ctrlKey, altKey, shiftKey, metaKey, altGraphKey);
-              break;
-            case 4:
-              args.push(key, location, modifiers, repeat, locale);
-              break;
-            default:
-              args.push(char, key, location, modifiers, repeat, locale);
-          }
-          out.initKeyboardEvent.apply(out, args);
-        } else {
-          out.initEvent(type, bubbles, cancelable);
-        }
-        for (key in out) {
-          if (defaults.hasOwnProperty(key) && out[key] !== init[key]) {
-            withInitValues(key, out, init);
-          }
-        }
-        return out;
-      }
-      KeyboardEvent.prototype = $KeyboardEvent.prototype;
-      return KeyboardEvent;
-    }(window.KeyboardEvent || function KeyboardEvent() {}));
-    defineProperty(window, 'KeyboardEvent', {value: o_O});
-    // Android 4 gotcha
-    if (KeyboardEvent !== o_O) KeyboardEvent = o_O;
-  }
-
-  // window.MouseEvent as constructor
-  try { new MouseEvent('_', {}); } catch (o_O) {
-    /* jshint -W022 */
-    o_O = (function ($MouseEvent) {
-      function MouseEvent(type, init) {
-        enoughArguments(arguments.length, 'MouseEvent');
-        var out = document.createEvent('MouseEvent');
-        if (!init) init = {};
-        out.initMouseEvent(
-          type,
-          !!init.bubbles,
-          !!init.cancelable,
-          init.view || window,
-          init.detail || 1,
-          init.screenX || 0,
-          init.screenY || 0,
-          init.clientX || 0,
-          init.clientY || 0,
-          !!init.ctrlKey,
-          !!init.altKey,
-          !!init.shiftKey,
-          !!init.metaKey,
-          init.button || 0,
-          init.relatedTarget || null
-        );
-        return out;
-      }
-      MouseEvent.prototype = $MouseEvent.prototype;
-      return MouseEvent;
-    }(window.MouseEvent || function MouseEvent() {}));
-    defineProperty(window, 'MouseEvent', {value: o_O});
-    // Android 4 gotcha
-    if (MouseEvent !== o_O) MouseEvent = o_O;
-  }
-
-  if (!document.querySelectorAll('*').forEach) {
-    (function () {
-      function patch(what) {
-        var querySelectorAll = what.querySelectorAll;
-        what.querySelectorAll = function qSA(css) {
-          var result = querySelectorAll.call(this, css);
-          result.forEach = Array.prototype.forEach;
-          return result;
-        };
-      }
-      patch(document);
-      patch(Element.prototype);
-    }());
-  }
-
-  try {
-    // https://drafts.csswg.org/selectors-4/#the-scope-pseudo
-    document.querySelector(':scope *');
-  } catch(o_O) {
-    (function () {
-      var dataScope = 'data-scope-' + (Math.random() * 1e9 >>> 0);
-      var proto = Element.prototype;
-      var querySelector = proto.querySelector;
-      var querySelectorAll = proto.querySelectorAll;
-      proto.querySelector = function qS(css) {
-        return find(this, querySelector, css);
-      };
-      proto.querySelectorAll = function qSA(css) {
-        return find(this, querySelectorAll, css);
-      };
-      function find(node, method, css) {
-        node.setAttribute(dataScope, null);
-        var result = method.call(
-          node,
-          String(css).replace(
-            /(^|,\s*)(:scope([ >]|$))/g,
-            function ($0, $1, $2, $3) {
-              return $1 + '[' + dataScope + ']' + ($3 || ' ');
-            }
-          )
-        );
-        node.removeAttribute(dataScope);
-        return result;
-      }
-    }());
-  }
-}(window));
-
-// prettier-ignore
-(function (global){'use strict';
-
-  // a WeakMap fallback for DOM nodes only used as key
-  var DOMMap = global.WeakMap || (function () {
-
-    var
-      counter = 0,
-      dispatched = false,
-      drop = false,
-      value
-    ;
-
-    function dispatch(key, ce, shouldDrop) {
-      drop = shouldDrop;
-      dispatched = false;
-      value = undefined;
-      key.dispatchEvent(ce);
-    }
-
-    function Handler(value) {
-      this.value = value;
-    }
-
-    Handler.prototype.handleEvent = function handleEvent(e) {
-      dispatched = true;
-      if (drop) {
-        e.currentTarget.removeEventListener(e.type, this, false);
-      } else {
-        value = this.value;
-      }
-    };
-
-    function DOMMap() {
-      counter++;  // make id clashing highly improbable
-      this.__ce__ = new Event(('@DOMMap:' + counter) + Math.random());
-    }
-
-    DOMMap.prototype = {
-      'constructor': DOMMap,
-      'delete': function del(key) {
-        return dispatch(key, this.__ce__, true), dispatched;
-      },
-      'get': function get(key) {
-        dispatch(key, this.__ce__, false);
-        var v = value;
-        value = undefined;
-        return v;
-      },
-      'has': function has(key) {
-        return dispatch(key, this.__ce__, false), dispatched;
-      },
-      'set': function set(key, value) {
-        dispatch(key, this.__ce__, true);
-        key.addEventListener(this.__ce__.type, new Handler(value), false);
-        return this;
-      },
-    };
-
-    return DOMMap;
-
-  }());
-
-  function Dict() {}
-  Dict.prototype = (Object.create || Object)(null);
-
-  // https://dom.spec.whatwg.org/#interface-eventtarget
-
-  function createEventListener(type, callback, options) {
-    function eventListener(e) {
-      if (eventListener.once) {
-        e.currentTarget.removeEventListener(
-          e.type,
-          callback,
-          eventListener
-        );
-        eventListener.removed = true;
-      }
-      if (eventListener.passive) {
-        e.preventDefault = createEventListener.preventDefault;
-      }
-      if (typeof eventListener.callback === 'function') {
-        /* jshint validthis: true */
-        eventListener.callback.call(this, e);
-      } else if (eventListener.callback) {
-        eventListener.callback.handleEvent(e);
-      }
-      if (eventListener.passive) {
-        delete e.preventDefault;
-      }
-    }
-    eventListener.type = type;
-    eventListener.callback = callback;
-    eventListener.capture = !!options.capture;
-    eventListener.passive = !!options.passive;
-    eventListener.once = !!options.once;
-    // currently pointless but specs say to use it, so ...
-    eventListener.removed = false;
-    return eventListener;
-  }
-
-  createEventListener.preventDefault = function preventDefault() {};
-
-  var
-    Event = global.CustomEvent,
-    dE = global.dispatchEvent,
-    aEL = global.addEventListener,
-    rEL = global.removeEventListener,
-    counter = 0,
-    increment = function () { counter++; },
-    indexOf = [].indexOf || function indexOf(value){
-      var length = this.length;
-      while(length--) {
-        if (this[length] === value) {
-          break;
-        }
-      }
-      return length;
-    },
-    getListenerKey = function (options) {
-      return ''.concat(
-        options.capture ? '1' : '0',
-        options.passive ? '1' : '0',
-        options.once ? '1' : '0'
-      );
-    },
-    augment
-  ;
-
-  try {
-    aEL('_', increment, {once: true});
-    dE(new Event('_'));
-    dE(new Event('_'));
-    rEL('_', increment, {once: true});
-  } catch(o_O) {}
-
-  if (counter !== 1) {
-    (function () {
-      var dm = new DOMMap();
-      function createAEL(aEL) {
-        return function addEventListener(type, handler, options) {
-          if (options && typeof options !== 'boolean') {
-            var
-              info = dm.get(this),
-              key = getListenerKey(options),
-              i, tmp, wrap
-            ;
-            if (!info) dm.set(this, (info = new Dict()));
-            if (!(type in info)) info[type] = {
-              handler: [],
-              wrap: []
-            };
-            tmp = info[type];
-            i = indexOf.call(tmp.handler, handler);
-            if (i < 0) {
-              i = tmp.handler.push(handler) - 1;
-              tmp.wrap[i] = (wrap = new Dict());
-            } else {
-              wrap = tmp.wrap[i];
-            }
-            if (!(key in wrap)) {
-              wrap[key] = createEventListener(type, handler, options);
-              aEL.call(this, type, wrap[key], wrap[key].capture);
-            }
-          } else {
-            aEL.call(this, type, handler, options);
-          }
-        };
-      }
-      function createREL(rEL) {
-        return function removeEventListener(type, handler, options) {
-          if (options && typeof options !== 'boolean') {
-            var
-              info = dm.get(this),
-              key, i, tmp, wrap
-            ;
-            if (info && (type in info)) {
-              tmp = info[type];
-              i = indexOf.call(tmp.handler, handler);
-              if (-1 < i) {
-                key = getListenerKey(options);
-                wrap = tmp.wrap[i];
-                if (key in wrap) {
-                  rEL.call(this, type, wrap[key], wrap[key].capture);
-                  delete wrap[key];
-                  // return if there are other wraps
-                  for (key in wrap) return;
-                  // otherwise remove all the things
-                  tmp.handler.splice(i, 1);
-                  tmp.wrap.splice(i, 1);
-                  // if there are no other handlers
-                  if (tmp.handler.length === 0)
-                    // drop the info[type] entirely
-                    delete info[type];
-                }
-              }
-            }
-          } else {
-            rEL.call(this, type, handler, options);
-          }
-        };
-      }
-
-      augment = function (Constructor) {
-        if (!Constructor) return;
-        var proto = Constructor.prototype;
-        proto.addEventListener = createAEL(proto.addEventListener);
-        proto.removeEventListener = createREL(proto.removeEventListener);
-      };
-
-      if (global.EventTarget) {
-        augment(EventTarget);
-      } else {
-        augment(global.Text);
-        augment(global.Element || global.HTMLElement);
-        augment(global.HTMLDocument);
-        augment(global.Window || {prototype:global});
-        augment(global.XMLHttpRequest);
-      }
-
-    }());
-  }
-
-}(window));
diff --git a/tgui/packages/tgui-polyfill/03-css-om.js b/tgui/packages/tgui-polyfill/03-css-om.js
deleted file mode 100644
index 0fb11eee280..00000000000
--- a/tgui/packages/tgui-polyfill/03-css-om.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * CSS Object Model patches
- *
- * Adapted from: https://github.com/shawnbot/aight
- *
- * @file
- * @copyright 2020 Aleksej Komarov
- * @license MIT
- */
-
-/* eslint-disable */
-// prettier-ignore
-(function(Proto) {
-  'use strict';
-
-  if (typeof Proto.setAttribute !== 'undefined') {
-    function toAttr(prop) {
-      return prop.replace(/-[a-z]/g, function (bit) {
-        return bit[1].toUpperCase();
-      });
-    }
-
-    Proto.setProperty = function (prop, value) {
-      var attr = toAttr(prop);
-      if (!value) {
-        return this.removeAttribute(attr);
-      }
-      var str = String(value);
-      return this.setAttribute(attr, str);
-    };
-
-    Proto.getPropertyValue = function (prop) {
-      var attr = toAttr(prop);
-      return this.getAttribute(attr) || null;
-    };
-
-    Proto.removeProperty = function (prop) {
-      var attr = toAttr(prop);
-      var value = this.getAttribute(attr);
-      this.removeAttribute(attr);
-      return value;
-    };
-  }
-
-})(CSSStyleDeclaration.prototype);
diff --git a/tgui/packages/tgui-polyfill/1-misc.js b/tgui/packages/tgui-polyfill/1-misc.js
new file mode 100644
index 00000000000..af9b900fe0b
--- /dev/null
+++ b/tgui/packages/tgui-polyfill/1-misc.js
@@ -0,0 +1,53 @@
+/**
+ * @file
+ * @copyright 2020 Aleksej Komarov
+ * @license MIT
+ */
+
+/* eslint-disable */
+(function () {
+  'use strict';
+
+  // Inferno needs Int32Array, and it is not covered by core-js.
+  if (!window.Int32Array) {
+    window.Int32Array = Array;
+  }
+
+  // ie11 polyfills
+  !(function () {
+    // append
+    function t() {
+      var e = Array.prototype.slice.call(arguments),
+        n = document.createDocumentFragment();
+      e.forEach(function (e) {
+        var t = e instanceof Node;
+        n.appendChild(t ? e : document.createTextNode(String(e)));
+      }),
+        this.appendChild(n);
+    }
+    // remove
+    function n() {
+      this.parentNode && this.parentNode.removeChild(this);
+    }
+
+    // add to prototype
+    [Element.prototype, Document.prototype, DocumentFragment.prototype].forEach(
+      function (e) {
+        e.hasOwnProperty('append') ||
+          Object.defineProperty(e, 'append', {
+            configurable: !0,
+            enumerable: !0,
+            writable: !0,
+            value: t,
+          });
+        e.hasOwnProperty('remove') ||
+          Object.defineProperty(e, 'remove', {
+            configurable: !0,
+            enumerable: !0,
+            writable: !0,
+            value: n,
+          });
+      }
+    );
+  })();
+})();
diff --git a/tgui/packages/tgui-polyfill/10-misc.js b/tgui/packages/tgui-polyfill/10-misc.js
deleted file mode 100644
index 9849166c2df..00000000000
--- a/tgui/packages/tgui-polyfill/10-misc.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * @file
- * @copyright 2020 Aleksej Komarov
- * @license MIT
- */
-
-/* eslint-disable */
-// prettier-ignore
-(function () {
-  'use strict';
-
-  // Necessary polyfill to make Webpack code splitting work on IE8
-  if (!Function.prototype.bind) (function () {
-    var slice = Array.prototype.slice;
-    Function.prototype.bind = function () {
-      var thatFunc = this, thatArg = arguments[0];
-      var args = slice.call(arguments, 1);
-      if (typeof thatFunc !== 'function') {
-        // closest thing possible to the ECMAScript 5
-        // internal IsCallable function
-        throw new TypeError('Function.prototype.bind - ' +
-          'what is trying to be bound is not callable');
-      }
-      return function () {
-        var funcArgs = args.concat(slice.call(arguments))
-        return thatFunc.apply(thatArg, funcArgs);
-      };
-    };
-  })();
-
-  if (!Array.prototype['forEach']) {
-    Array.prototype.forEach = function (callback, thisArg) {
-      if (this == null) {
-        throw new TypeError('Array.prototype.forEach called on null or undefined');
-      }
-      var T, k;
-      var O = Object(this);
-      var len = O.length >>> 0;
-      if (typeof callback !== "function") {
-        throw new TypeError(callback + ' is not a function');
-      }
-      if (arguments.length > 1) {
-        T = thisArg;
-      }
-      k = 0;
-      while (k < len) {
-        var kValue;
-        if (k in O) {
-          kValue = O[k];
-          callback.call(T, kValue, k, O);
-        }
-        k++;
-      }
-    };
-  }
-
-  // Inferno needs Int32Array, and it is not covered by core-js.
-  if (!window.Int32Array) {
-    window.Int32Array = Array;
-  }
-
-})();
diff --git a/tgui/packages/tgui-polyfill/package.json b/tgui/packages/tgui-polyfill/package.json
index 227d192faa6..c0cb0911160 100644
--- a/tgui/packages/tgui-polyfill/package.json
+++ b/tgui/packages/tgui-polyfill/package.json
@@ -1,9 +1,9 @@
 {
   "private": true,
   "name": "tgui-polyfill",
-  "version": "4.3.2",
+  "version": "4.4.0",
   "scripts": {
-    "tgui-polyfill:build": "terser 00-html5shiv.js 01-ie8.js 02-dom4.js 03-css-om.js 10-misc.js --ie8 -f ascii_only,comments=false -o ../../public/tgui-polyfill.min.js"
+    "tgui-polyfill:build": "terser 1-misc.js -f ascii_only,comments=false -o ../../public/tgui-polyfill.min.js"
   },
   "dependencies": {
     "core-js": "^3.33.3",
diff --git a/tgui/packages/tgui/package.json b/tgui/packages/tgui/package.json
index 12fa809139e..d7cdd701db4 100644
--- a/tgui/packages/tgui/package.json
+++ b/tgui/packages/tgui/package.json
@@ -1,7 +1,7 @@
 {
   "private": true,
   "name": "tgui",
-  "version": "4.3.2",
+  "version": "4.4.0",
   "dependencies": {
     "@popperjs/core": "^2.11.8",
     "@types/marked": "^4.0.8",
diff --git a/tgui/public/tgui-polyfill.min.js b/tgui/public/tgui-polyfill.min.js
index 91be6dc8765..68c21147e6d 100644
--- a/tgui/public/tgui-polyfill.min.js
+++ b/tgui/public/tgui-polyfill.min.js
@@ -1 +1 @@
-(function(window,document){var version="3.7.3";var options=window.html5||{};var reSkip=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;var saveClones=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;var supportsHtml5Styles;var expando="_html5shiv";var expanID=0;var expandoData={};var supportsUnknownElements;(function(){try{var a=document.createElement("a");a.innerHTML="<xyz></xyz>";supportsHtml5Styles="hidden"in a;supportsUnknownElements=a.childNodes.length==1||function(){document.createElement("a");var frag=document.createDocumentFragment();return typeof frag.cloneNode=="undefined"||typeof frag.createDocumentFragment=="undefined"||typeof frag.createElement=="undefined"}()}catch(e){supportsHtml5Styles=true;supportsUnknownElements=true}})();function addStyleSheet(ownerDocument,cssText){var p=ownerDocument.createElement("p"),parent=ownerDocument.getElementsByTagName("head")[0]||ownerDocument.documentElement;p.innerHTML="x<style>"+cssText+"</style>";return parent.insertBefore(p.lastChild,parent.firstChild)}function getElements(){var elements=html5.elements;return typeof elements=="string"?elements.split(" "):elements}function addElements(newElements,ownerDocument){var elements=html5.elements;if(typeof elements!="string"){elements=elements.join(" ")}if(typeof newElements!="string"){newElements=newElements.join(" ")}html5.elements=elements+" "+newElements;shivDocument(ownerDocument)}function getExpandoData(ownerDocument){var data=expandoData[ownerDocument[expando]];if(!data){data={};expanID++;ownerDocument[expando]=expanID;expandoData[expanID]=data}return data}function createElement(nodeName,ownerDocument,data){if(!ownerDocument){ownerDocument=document}if(supportsUnknownElements){return ownerDocument.createElement(nodeName)}if(!data){data=getExpandoData(ownerDocument)}var node;if(data.cache[nodeName]){node=data.cache[nodeName].cloneNode()}else if(saveClones.test(nodeName)){node=(data.cache[nodeName]=data.createElem(nodeName)).cloneNode()}else{node=data.createElem(nodeName)}return node.canHaveChildren&&!reSkip.test(nodeName)&&!node.tagUrn?data.frag.appendChild(node):node}function createDocumentFragment(ownerDocument,data){if(!ownerDocument){ownerDocument=document}if(supportsUnknownElements){return ownerDocument.createDocumentFragment()}data=data||getExpandoData(ownerDocument);var clone=data.frag.cloneNode(),i=0,elems=getElements(),l=elems.length;for(;i<l;i++){clone.createElement(elems[i])}return clone}function shivMethods(ownerDocument,data){if(!data.cache){data.cache={};data.createElem=ownerDocument.createElement;data.createFrag=ownerDocument.createDocumentFragment;data.frag=data.createFrag()}ownerDocument.createElement=function(nodeName){if(!html5.shivMethods){return data.createElem(nodeName)}return createElement(nodeName,ownerDocument,data)};ownerDocument.createDocumentFragment=Function("h,f","return function(){"+"var n=f.cloneNode(),c=n.createElement;"+"h.shivMethods&&("+getElements().join().replace(/[\w\-:]+/g,(function(nodeName){data.createElem(nodeName);data.frag.createElement(nodeName);return'c("'+nodeName+'")'}))+");return n}")(html5,data.frag)}function shivDocument(ownerDocument){if(!ownerDocument){ownerDocument=document}var data=getExpandoData(ownerDocument);if(html5.shivCSS&&!supportsHtml5Styles&&!data.hasCSS){data.hasCSS=!!addStyleSheet(ownerDocument,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}"+"mark{background:#FF0;color:#000}"+"template{display:none}")}if(!supportsUnknownElements){shivMethods(ownerDocument,data)}return ownerDocument}var html5={elements:options.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:version,shivCSS:options.shivCSS!==false,supportsUnknownElements:supportsUnknownElements,shivMethods:options.shivMethods!==false,type:"default",shivDocument:shivDocument,createElement:createElement,createDocumentFragment:createDocumentFragment,addElements:addElements};window.html5=html5;shivDocument(document);if(typeof module=="object"&&module.exports){module.exports=html5}})(window,document);(function(window){if(document.createEvent)return;var DUNNOABOUTDOMLOADED=true,READYEVENTDISPATCHED=false,ONREADYSTATECHANGE="onreadystatechange",DOMCONTENTLOADED="DOMContentLoaded",SECRET="__IE8__"+Math.random(),defineProperty=Object.defineProperty||function(object,property,descriptor){object[property]=descriptor.value},defineProperties=Object.defineProperties||function(object,descriptors){for(var key in descriptors){if(hasOwnProperty.call(descriptors,key)){try{defineProperty(object,key,descriptors[key])}catch(o_O){if(window.console){console.log(key+" failed on object:",object,o_O.message)}}}}},getOwnPropertyDescriptor=Object.getOwnPropertyDescriptor,hasOwnProperty=Object.prototype.hasOwnProperty,ElementPrototype=window.Element.prototype,TextPrototype=window.Text.prototype,possiblyNativeEvent=/^[a-z]+$/,readyStateOK=/loaded|complete/,types={},div=document.createElement("div"),html=document.documentElement,removeAttribute=html.removeAttribute,setAttribute=html.setAttribute,valueDesc=function(value){return{enumerable:true,writable:true,configurable:true,value:value}};function commonEventLoop(currentTarget,e,$handlers,synthetic){for(var handler,continuePropagation,handlers=$handlers.slice(),evt=enrich(e,currentTarget),i=0,length=handlers.length;i<length;i++){handler=handlers[i];if(typeof handler==="object"){if(typeof handler.handleEvent==="function"){handler.handleEvent(evt)}}else{handler.call(currentTarget,evt)}if(evt.stoppedImmediatePropagation)break}continuePropagation=!evt.stoppedPropagation;return synthetic&&continuePropagation&&currentTarget.parentNode?currentTarget.parentNode.dispatchEvent(evt):!evt.defaultPrevented}function commonDescriptor(get,set){return{configurable:true,get:get,set:set}}function commonTextContent(protoDest,protoSource,property){var descriptor=getOwnPropertyDescriptor(protoSource||protoDest,property);defineProperty(protoDest,"textContent",commonDescriptor((function(){return descriptor.get.call(this)}),(function(textContent){descriptor.set.call(this,textContent)})))}function enrich(e,currentTarget){e.currentTarget=currentTarget;e.eventPhase=e.target===e.currentTarget?2:3;return e}function find(array,value){var i=array.length;while(i--&&array[i]!==value);return i}function getTextContent(){if(this.tagName==="BR")return"\n";var textNode=this.firstChild,arrayContent=[];while(textNode){if(textNode.nodeType!==8&&textNode.nodeType!==7){arrayContent.push(textNode.textContent)}textNode=textNode.nextSibling}return arrayContent.join("")}function live(self){return self.nodeType!==9&&html.contains(self)}function onkeyup(e){var evt=document.createEvent("Event");evt.initEvent("input",true,true);(e.srcElement||e.fromElement||document).dispatchEvent(evt)}function onReadyState(e){if(!READYEVENTDISPATCHED&&readyStateOK.test(document.readyState)){READYEVENTDISPATCHED=!READYEVENTDISPATCHED;document.detachEvent(ONREADYSTATECHANGE,onReadyState);e=document.createEvent("Event");e.initEvent(DOMCONTENTLOADED,true,true);document.dispatchEvent(e)}}function getter(attr){return function(){return html[attr]||document.body&&document.body[attr]||0}}function setTextContent(textContent){var node;while(node=this.lastChild){this.removeChild(node)}if(textContent!=null){this.appendChild(document.createTextNode(textContent))}}function verify(self,e){if(!e){e=window.event}if(!e.target){e.target=e.srcElement||e.fromElement||document}if(!e.timeStamp){e.timeStamp=(new Date).getTime()}return e}commonTextContent(window.HTMLCommentElement.prototype,ElementPrototype,"nodeValue");commonTextContent(window.HTMLScriptElement.prototype,null,"text");commonTextContent(TextPrototype,null,"nodeValue");commonTextContent(window.HTMLTitleElement.prototype,null,"text");defineProperty(window.HTMLStyleElement.prototype,"textContent",function(descriptor){return commonDescriptor((function(){return descriptor.get.call(this.styleSheet)}),(function(textContent){descriptor.set.call(this.styleSheet,textContent)}))}(getOwnPropertyDescriptor(window.CSSStyleSheet.prototype,"cssText")));var opacityre=/\b\s*alpha\s*\(\s*opacity\s*=\s*(\d+)\s*\)/;defineProperty(window.CSSStyleDeclaration.prototype,"opacity",{get:function(){var m=this.filter.match(opacityre);return m?(m[1]/100).toString():""},set:function(value){this.zoom=1;var found=false;if(value<1){value=" alpha(opacity="+Math.round(value*100)+")"}else{value=""}this.filter=this.filter.replace(opacityre,(function(){found=true;return value}));if(!found&&value){this.filter+=value}}});defineProperties(ElementPrototype,{textContent:{get:getTextContent,set:setTextContent},firstElementChild:{get:function(){for(var childNodes=this.childNodes||[],i=0,length=childNodes.length;i<length;i++){if(childNodes[i].nodeType==1)return childNodes[i]}}},lastElementChild:{get:function(){for(var childNodes=this.childNodes||[],i=childNodes.length;i--;){if(childNodes[i].nodeType==1)return childNodes[i]}}},oninput:{get:function(){return this._oninput||null},set:function(oninput){if(this._oninput){this.removeEventListener("input",this._oninput);this._oninput=oninput;if(oninput){this.addEventListener("input",oninput)}}}},previousElementSibling:{get:function(){var previousElementSibling=this.previousSibling;while(previousElementSibling&&previousElementSibling.nodeType!=1){previousElementSibling=previousElementSibling.previousSibling}return previousElementSibling}},nextElementSibling:{get:function(){var nextElementSibling=this.nextSibling;while(nextElementSibling&&nextElementSibling.nodeType!=1){nextElementSibling=nextElementSibling.nextSibling}return nextElementSibling}},childElementCount:{get:function(){for(var count=0,childNodes=this.childNodes||[],i=childNodes.length;i--;count+=childNodes[i].nodeType==1);return count}},addEventListener:valueDesc((function(type,handler,capture){if(typeof handler!=="function"&&typeof handler!=="object")return;var self=this,ontype="on"+type,temple=self[SECRET]||defineProperty(self,SECRET,{value:{}})[SECRET],currentType=temple[ontype]||(temple[ontype]={}),handlers=currentType.h||(currentType.h=[]),e,attr;if(!hasOwnProperty.call(currentType,"w")){currentType.w=function(e){return e[SECRET]||commonEventLoop(self,verify(self,e),handlers,false)};if(!hasOwnProperty.call(types,ontype)){if(possiblyNativeEvent.test(type)){try{e=document.createEventObject();e[SECRET]=true;if(self.nodeType!=9){if(self.parentNode==null){div.appendChild(self)}if(attr=self.getAttribute(ontype)){removeAttribute.call(self,ontype)}}self.fireEvent(ontype,e);types[ontype]=true}catch(meh){types[ontype]=false;while(div.hasChildNodes()){div.removeChild(div.firstChild)}}if(attr!=null){setAttribute.call(self,ontype,attr)}}else{types[ontype]=false}}if(currentType.n=types[ontype]){self.attachEvent(ontype,currentType.w)}}if(find(handlers,handler)<0){handlers[capture?"unshift":"push"](handler)}if(type==="input"){self.attachEvent("onkeyup",onkeyup)}})),dispatchEvent:valueDesc((function(e){var self=this,ontype="on"+e.type,temple=self[SECRET],currentType=temple&&temple[ontype],valid=!!currentType,parentNode;if(!e.target)e.target=self;return valid?currentType.n?self.fireEvent(ontype,e):commonEventLoop(self,e,currentType.h,true):(parentNode=self.parentNode)?parentNode.dispatchEvent(e):true,!e.defaultPrevented})),removeEventListener:valueDesc((function(type,handler,capture){if(typeof handler!=="function"&&typeof handler!=="object")return;var self=this,ontype="on"+type,temple=self[SECRET],currentType=temple&&temple[ontype],handlers=currentType&&currentType.h,i=handlers?find(handlers,handler):-1;if(-1<i)handlers.splice(i,1)}))});defineProperties(TextPrototype,{addEventListener:valueDesc(ElementPrototype.addEventListener),dispatchEvent:valueDesc(ElementPrototype.dispatchEvent),removeEventListener:valueDesc(ElementPrototype.removeEventListener)});defineProperties(window.XMLHttpRequest.prototype,{addEventListener:valueDesc((function(type,handler,capture){var self=this,ontype="on"+type,temple=self[SECRET]||defineProperty(self,SECRET,{value:{}})[SECRET],currentType=temple[ontype]||(temple[ontype]={}),handlers=currentType.h||(currentType.h=[]);if(find(handlers,handler)<0){if(!self[ontype]){self[ontype]=function(){var e=document.createEvent("Event");e.initEvent(type,true,true);self.dispatchEvent(e)}}handlers[capture?"unshift":"push"](handler)}})),dispatchEvent:valueDesc((function(e){var self=this,ontype="on"+e.type,temple=self[SECRET],currentType=temple&&temple[ontype],valid=!!currentType;return valid&&(currentType.n?self.fireEvent(ontype,e):commonEventLoop(self,e,currentType.h,true))})),removeEventListener:valueDesc(ElementPrototype.removeEventListener)});var buttonGetter=getOwnPropertyDescriptor(Event.prototype,"button").get;defineProperties(window.Event.prototype,{bubbles:valueDesc(true),cancelable:valueDesc(true),preventDefault:valueDesc((function(){if(this.cancelable){this.returnValue=false}})),stopPropagation:valueDesc((function(){this.stoppedPropagation=true;this.cancelBubble=true})),stopImmediatePropagation:valueDesc((function(){this.stoppedImmediatePropagation=true;this.stopPropagation()})),initEvent:valueDesc((function(type,bubbles,cancelable){this.type=type;this.bubbles=!!bubbles;this.cancelable=!!cancelable;if(!this.bubbles){this.stopPropagation()}})),pageX:{get:function(){return this._pageX||(this._pageX=this.clientX+window.scrollX-(html.clientLeft||0))}},pageY:{get:function(){return this._pageY||(this._pageY=this.clientY+window.scrollY-(html.clientTop||0))}},which:{get:function(){return this.keyCode?this.keyCode:isNaN(this.button)?undefined:this.button+1}},charCode:{get:function(){return this.keyCode&&this.type=="keypress"?this.keyCode:0}},buttons:{get:function(){return buttonGetter.call(this)}},button:{get:function(){var buttons=this.buttons;return buttons&1?0:buttons&2?2:buttons&4?1:undefined}},defaultPrevented:{get:function(){var returnValue=this.returnValue,undef;return!(returnValue===undef||returnValue)}},relatedTarget:{get:function(){var type=this.type;if(type==="mouseover"){return this.fromElement}else if(type==="mouseout"){return this.toElement}else{return null}}}});defineProperties(window.HTMLDocument.prototype,{defaultView:{get:function(){return this.parentWindow}},textContent:{get:function(){return this.nodeType===11?getTextContent.call(this):null},set:function(textContent){if(this.nodeType===11){setTextContent.call(this,textContent)}}},addEventListener:valueDesc((function(type,handler,capture){var self=this;ElementPrototype.addEventListener.call(self,type,handler,capture);if(DUNNOABOUTDOMLOADED&&type===DOMCONTENTLOADED&&!readyStateOK.test(self.readyState)){DUNNOABOUTDOMLOADED=false;self.attachEvent(ONREADYSTATECHANGE,onReadyState);if(window==top){(function gonna(e){try{self.documentElement.doScroll("left");onReadyState()}catch(o_O){setTimeout(gonna,50)}})()}}})),dispatchEvent:valueDesc(ElementPrototype.dispatchEvent),removeEventListener:valueDesc(ElementPrototype.removeEventListener),createEvent:valueDesc((function(Class){var e;if(Class!=="Event")throw new Error("unsupported "+Class);e=document.createEventObject();e.timeStamp=(new Date).getTime();return e}))});defineProperties(window.Window.prototype,{getComputedStyle:valueDesc(function(){var notpixel=/^(?:[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/,position=/^(top|right|bottom|left)$/,re=/\-([a-z])/g,place=function(match,$1){return $1.toUpperCase()};function ComputedStyle(_){this._=_}ComputedStyle.prototype.getPropertyValue=function(name){var el=this._,style=el.style,currentStyle=el.currentStyle,runtimeStyle=el.runtimeStyle,result,left,rtLeft;if(name=="opacity"){return style.opacity||"1"}name=(name==="float"?"style-float":name).replace(re,place);result=currentStyle?currentStyle[name]:style[name];if(notpixel.test(result)&&!position.test(name)){left=style.left;rtLeft=runtimeStyle&&runtimeStyle.left;if(rtLeft){runtimeStyle.left=currentStyle.left}style.left=name==="fontSize"?"1em":result;result=style.pixelLeft+"px";style.left=left;if(rtLeft){runtimeStyle.left=rtLeft}}return result==null?result:result+""||"auto"};function PseudoComputedStyle(){}PseudoComputedStyle.prototype.getPropertyValue=function(){return null};return function(el,pseudo){return pseudo?new PseudoComputedStyle(el):new ComputedStyle(el)}}()),addEventListener:valueDesc((function(type,handler,capture){var self=window,ontype="on"+type,handlers;if(!self[ontype]){self[ontype]=function(e){return commonEventLoop(self,verify(self,e),handlers,false)&&undefined}}handlers=self[ontype][SECRET]||(self[ontype][SECRET]=[]);if(find(handlers,handler)<0){handlers[capture?"unshift":"push"](handler)}})),dispatchEvent:valueDesc((function(e){var method=window["on"+e.type];return method?method.call(window,e)!==false&&!e.defaultPrevented:true})),removeEventListener:valueDesc((function(type,handler,capture){var ontype="on"+type,handlers=(window[ontype]||Object)[SECRET],i=handlers?find(handlers,handler):-1;if(-1<i)handlers.splice(i,1)})),pageXOffset:{get:getter("scrollLeft")},pageYOffset:{get:getter("scrollTop")},scrollX:{get:getter("scrollLeft")},scrollY:{get:getter("scrollTop")},innerWidth:{get:getter("clientWidth")},innerHeight:{get:getter("clientHeight")}});window.HTMLElement=window.Element;(function(styleSheets,HTML5Element,i){for(i=0;i<HTML5Element.length;i++)document.createElement(HTML5Element[i]);if(!styleSheets.length)document.createStyleSheet("");styleSheets[0].addRule(HTML5Element.join(","),"display:block;")})(document.styleSheets,["header","nav","section","article","aside","footer"]);(function(){if(document.createRange)return;document.createRange=function createRange(){return new Range};function getContents(start,end){var nodes=[start];while(start!==end){nodes.push(start=start.nextSibling)}return nodes}function Range(){}var proto=Range.prototype;proto.cloneContents=function cloneContents(){for(var fragment=this._start.ownerDocument.createDocumentFragment(),nodes=getContents(this._start,this._end),i=0,length=nodes.length;i<length;i++){fragment.appendChild(nodes[i].cloneNode(true))}return fragment};proto.cloneRange=function cloneRange(){var range=new Range;range._start=this._start;range._end=this._end;return range};proto.deleteContents=function deleteContents(){for(var parentNode=this._start.parentNode,nodes=getContents(this._start,this._end),i=0,length=nodes.length;i<length;i++){parentNode.removeChild(nodes[i])}};proto.extractContents=function extractContents(){for(var fragment=this._start.ownerDocument.createDocumentFragment(),nodes=getContents(this._start,this._end),i=0,length=nodes.length;i<length;i++){fragment.appendChild(nodes[i])}return fragment};proto.setEndAfter=function setEndAfter(node){this._end=node};proto.setEndBefore=function setEndBefore(node){this._end=node.previousSibling};proto.setStartAfter=function setStartAfter(node){this._start=node.nextSibling};proto.setStartBefore=function setStartBefore(node){this._start=node}})()})(window);(function(window){"use strict";function createDocumentFragment(){return document.createDocumentFragment()}function createElement(nodeName){return document.createElement(nodeName)}function enoughArguments(length,name){if(!length)throw new Error("Failed to construct "+name+": 1 argument required, but only 0 present.")}function mutationMacro(nodes){if(nodes.length===1){return textNodeIfPrimitive(nodes[0])}for(var fragment=createDocumentFragment(),list=slice.call(nodes),i=0;i<nodes.length;i++){fragment.appendChild(textNodeIfPrimitive(list[i]))}return fragment}function textNodeIfPrimitive(node){return typeof node==="object"?node:document.createTextNode(node)}for(var head,property,TemporaryPrototype,TemporaryTokenList,wrapVerifyToken,document=window.document,hOP=Object.prototype.hasOwnProperty,defineProperty=Object.defineProperty||function(object,property,descriptor){if(hOP.call(descriptor,"value")){object[property]=descriptor.value}else{if(hOP.call(descriptor,"get"))object.__defineGetter__(property,descriptor.get);if(hOP.call(descriptor,"set"))object.__defineSetter__(property,descriptor.set)}return object},indexOf=[].indexOf||function indexOf(value){var length=this.length;while(length--){if(this[length]===value){break}}return length},verifyToken=function(token){if(!token){throw"SyntaxError"}else if(spaces.test(token)){throw"InvalidCharacterError"}return token},DOMTokenList=function(node){var noClassName=typeof node.className==="undefined",className=noClassName?node.getAttribute("class")||"":node.className,isSVG=noClassName||typeof className==="object",value=(isSVG?noClassName?className:className.baseVal:className).replace(trim,"");if(value.length){properties.push.apply(this,value.split(spaces))}this._isSVG=isSVG;this._=node},classListDescriptor={get:function get(){return new DOMTokenList(this)},set:function(){}},trim=/^\s+|\s+$/g,spaces=/\s+/,SPACE=" ",CLASS_LIST="classList",toggle=function toggle(token,force){if(this.contains(token)){if(!force){this.remove(token)}}else if(force===undefined||force){force=true;this.add(token)}return!!force},DocumentFragmentPrototype=window.DocumentFragment&&DocumentFragment.prototype,Node=window.Node,NodePrototype=(Node||Element).prototype,CharacterData=window.CharacterData||Node,CharacterDataPrototype=CharacterData&&CharacterData.prototype,DocumentType=window.DocumentType,DocumentTypePrototype=DocumentType&&DocumentType.prototype,ElementPrototype=(window.Element||Node||window.HTMLElement).prototype,HTMLSelectElement=window.HTMLSelectElement||createElement("select").constructor,selectRemove=HTMLSelectElement.prototype.remove,SVGElement=window.SVGElement,properties=["matches",ElementPrototype.matchesSelector||ElementPrototype.webkitMatchesSelector||ElementPrototype.khtmlMatchesSelector||ElementPrototype.mozMatchesSelector||ElementPrototype.msMatchesSelector||ElementPrototype.oMatchesSelector||function matches(selector){var parentNode=this.parentNode;return!!parentNode&&-1<indexOf.call(parentNode.querySelectorAll(selector),this)},"closest",function closest(selector){var parentNode=this,matches;while((matches=parentNode&&parentNode.matches)&&!parentNode.matches(selector)){parentNode=parentNode.parentNode}return matches?parentNode:null},"prepend",function prepend(){var firstChild=this.firstChild,node=mutationMacro(arguments);if(firstChild){this.insertBefore(node,firstChild)}else{this.appendChild(node)}},"append",function append(){this.appendChild(mutationMacro(arguments))},"before",function before(){var parentNode=this.parentNode;if(parentNode){parentNode.insertBefore(mutationMacro(arguments),this)}},"after",function after(){var parentNode=this.parentNode,nextSibling=this.nextSibling,node=mutationMacro(arguments);if(parentNode){if(nextSibling){parentNode.insertBefore(node,nextSibling)}else{parentNode.appendChild(node)}}},"toggleAttribute",function toggleAttribute(name,force){var had=this.hasAttribute(name);if(1<arguments.length){if(had&&!force)this.removeAttribute(name);else if(force&&!had)this.setAttribute(name,"")}else if(had)this.removeAttribute(name);else this.setAttribute(name,"");return this.hasAttribute(name)},"replace",function replace(){this.replaceWith.apply(this,arguments)},"replaceWith",function replaceWith(){var parentNode=this.parentNode;if(parentNode){parentNode.replaceChild(mutationMacro(arguments),this)}},"remove",function remove(){var parentNode=this.parentNode;if(parentNode){parentNode.removeChild(this)}}],slice=properties.slice,i=properties.length;i;i-=2){property=properties[i-2];if(!(property in ElementPrototype)){ElementPrototype[property]=properties[i-1]}if(property==="remove"&&!selectRemove._dom4){(HTMLSelectElement.prototype[property]=function(){return 0<arguments.length?selectRemove.apply(this,arguments):ElementPrototype.remove.call(this)})._dom4=true}if(/^(?:before|after|replace|replaceWith|remove)$/.test(property)){if(CharacterData&&!(property in CharacterDataPrototype)){CharacterDataPrototype[property]=properties[i-1]}if(DocumentType&&!(property in DocumentTypePrototype)){DocumentTypePrototype[property]=properties[i-1]}}if(/^(?:append|prepend)$/.test(property)){if(DocumentFragmentPrototype){if(!(property in DocumentFragmentPrototype)){DocumentFragmentPrototype[property]=properties[i-1]}}else{try{createDocumentFragment().constructor.prototype[property]=properties[i-1]}catch(o_O){}}}}if(!createElement("a").matches("a")){ElementPrototype[property]=function(matches){return function(selector){return matches.call(this.parentNode?this:createDocumentFragment().appendChild(this),selector)}}(ElementPrototype[property])}DOMTokenList.prototype={length:0,add:function add(){for(var j=0,token;j<arguments.length;j++){token=arguments[j];if(!this.contains(token)){properties.push.call(this,property)}}if(this._isSVG){this._.setAttribute("class",""+this)}else{this._.className=""+this}},contains:function(indexOf){return function contains(token){i=indexOf.call(this,property=verifyToken(token));return-1<i}}([].indexOf||function(token){i=this.length;while(i--&&this[i]!==token){}return i}),item:function item(i){return this[i]||null},remove:function remove(){for(var j=0,token;j<arguments.length;j++){token=arguments[j];if(this.contains(token)){properties.splice.call(this,i,1)}}if(this._isSVG){this._.setAttribute("class",""+this)}else{this._.className=""+this}},toggle:toggle,toString:function toString(){return properties.join.call(this,SPACE)}};if(SVGElement&&!(CLASS_LIST in SVGElement.prototype)){defineProperty(SVGElement.prototype,CLASS_LIST,classListDescriptor)}if(!(CLASS_LIST in document.documentElement)){defineProperty(ElementPrototype,CLASS_LIST,classListDescriptor)}else{TemporaryTokenList=createElement("div")[CLASS_LIST];TemporaryTokenList.add("a","b","a");if("a b"!=TemporaryTokenList){TemporaryPrototype=TemporaryTokenList.constructor.prototype;if(!("add"in TemporaryPrototype)){TemporaryPrototype=window.TemporaryTokenList.prototype}wrapVerifyToken=function(original){return function(){var i=0;while(i<arguments.length){original.call(this,arguments[i++])}}};TemporaryPrototype.add=wrapVerifyToken(TemporaryPrototype.add);TemporaryPrototype.remove=wrapVerifyToken(TemporaryPrototype.remove);TemporaryPrototype.toggle=toggle}}if(!("contains"in NodePrototype)){defineProperty(NodePrototype,"contains",{value:function(el){while(el&&el!==this)el=el.parentNode;return this===el}})}if(!("head"in document)){defineProperty(document,"head",{get:function(){return head||(head=document.getElementsByTagName("head")[0])}})}(function(){for(var raf,rAF=window.requestAnimationFrame,cAF=window.cancelAnimationFrame,prefixes=["o","ms","moz","webkit"],i=prefixes.length;!cAF&&i--;){rAF=rAF||window[prefixes[i]+"RequestAnimationFrame"];cAF=window[prefixes[i]+"CancelAnimationFrame"]||window[prefixes[i]+"CancelRequestAnimationFrame"]}if(!cAF){if(rAF){raf=rAF;rAF=function(callback){var goOn=true;raf((function(){if(goOn)callback.apply(this,arguments)}));return function(){goOn=false}};cAF=function(id){id()}}else{rAF=function(callback){return setTimeout(callback,15,15)};cAF=function(id){clearTimeout(id)}}}window.requestAnimationFrame=rAF;window.cancelAnimationFrame=cAF})();try{new window.CustomEvent("?")}catch(o_O){window.CustomEvent=function(eventName,defaultInitDict){function CustomEvent(type,eventInitDict){var event=document.createEvent(eventName);if(typeof type!="string"){throw new Error("An event name must be provided")}if(eventName=="Event"){event.initCustomEvent=initCustomEvent}if(eventInitDict==null){eventInitDict=defaultInitDict}event.initCustomEvent(type,eventInitDict.bubbles,eventInitDict.cancelable,eventInitDict.detail);return event}function initCustomEvent(type,bubbles,cancelable,detail){this.initEvent(type,bubbles,cancelable);this.detail=detail}return CustomEvent}(window.CustomEvent?"CustomEvent":"Event",{bubbles:false,cancelable:false,detail:null})}try{new Event("_")}catch(o_O){o_O=function($Event){function Event(type,init){enoughArguments(arguments.length,"Event");var out=document.createEvent("Event");if(!init)init={};out.initEvent(type,!!init.bubbles,!!init.cancelable);return out}Event.prototype=$Event.prototype;return Event}(window.Event||function Event(){});defineProperty(window,"Event",{value:o_O});if(Event!==o_O)Event=o_O}try{new KeyboardEvent("_",{})}catch(o_O){o_O=function($KeyboardEvent){var initType=0,defaults={char:"",key:"",location:0,ctrlKey:false,shiftKey:false,altKey:false,metaKey:false,altGraphKey:false,repeat:false,locale:navigator.language,detail:0,bubbles:false,cancelable:false,keyCode:0,charCode:0,which:0},eventType;try{var e=document.createEvent("KeyboardEvent");e.initKeyboardEvent("keyup",false,false,window,"+",3,true,false,true,false,false);initType=(e.keyIdentifier||e.key)=="+"&&(e.keyLocation||e.location)==3&&(e.ctrlKey?e.altKey?1:3:e.shiftKey?2:4)||9}catch(o_O){}eventType=0<initType?"KeyboardEvent":"Event";function getModifier(init){for(var out=[],keys=["ctrlKey","Control","shiftKey","Shift","altKey","Alt","metaKey","Meta","altGraphKey","AltGraph"],i=0;i<keys.length;i+=2){if(init[keys[i]])out.push(keys[i+1])}return out.join(" ")}function withDefaults(target,source){for(var key in source){if(source.hasOwnProperty(key)&&!source.hasOwnProperty.call(target,key))target[key]=source[key]}return target}function withInitValues(key,out,init){try{out[key]=init[key]}catch(o_O){}}function KeyboardEvent(type,init){enoughArguments(arguments.length,"KeyboardEvent");init=withDefaults(init||{},defaults);var out=document.createEvent(eventType),ctrlKey=init.ctrlKey,shiftKey=init.shiftKey,altKey=init.altKey,metaKey=init.metaKey,altGraphKey=init.altGraphKey,modifiers=initType>3?getModifier(init):null,key=String(init.key),chr=String(init.char),location=init.location,keyCode=init.keyCode||(init.keyCode=key)&&key.charCodeAt(0)||0,charCode=init.charCode||(init.charCode=chr)&&chr.charCodeAt(0)||0,bubbles=init.bubbles,cancelable=init.cancelable,repeat=init.repeat,locale=init.locale,view=init.view||window,args;if(!init.which)init.which=init.keyCode;if("initKeyEvent"in out){out.initKeyEvent(type,bubbles,cancelable,view,ctrlKey,altKey,shiftKey,metaKey,keyCode,charCode)}else if(0<initType&&"initKeyboardEvent"in out){args=[type,bubbles,cancelable,view];switch(initType){case 1:args.push(key,location,ctrlKey,shiftKey,altKey,metaKey,altGraphKey);break;case 2:args.push(ctrlKey,altKey,shiftKey,metaKey,keyCode,charCode);break;case 3:args.push(key,location,ctrlKey,altKey,shiftKey,metaKey,altGraphKey);break;case 4:args.push(key,location,modifiers,repeat,locale);break;default:args.push(char,key,location,modifiers,repeat,locale)}out.initKeyboardEvent.apply(out,args)}else{out.initEvent(type,bubbles,cancelable)}for(key in out){if(defaults.hasOwnProperty(key)&&out[key]!==init[key]){withInitValues(key,out,init)}}return out}KeyboardEvent.prototype=$KeyboardEvent.prototype;return KeyboardEvent}(window.KeyboardEvent||function KeyboardEvent(){});defineProperty(window,"KeyboardEvent",{value:o_O});if(KeyboardEvent!==o_O)KeyboardEvent=o_O}try{new MouseEvent("_",{})}catch(o_O){o_O=function($MouseEvent){function MouseEvent(type,init){enoughArguments(arguments.length,"MouseEvent");var out=document.createEvent("MouseEvent");if(!init)init={};out.initMouseEvent(type,!!init.bubbles,!!init.cancelable,init.view||window,init.detail||1,init.screenX||0,init.screenY||0,init.clientX||0,init.clientY||0,!!init.ctrlKey,!!init.altKey,!!init.shiftKey,!!init.metaKey,init.button||0,init.relatedTarget||null);return out}MouseEvent.prototype=$MouseEvent.prototype;return MouseEvent}(window.MouseEvent||function MouseEvent(){});defineProperty(window,"MouseEvent",{value:o_O});if(MouseEvent!==o_O)MouseEvent=o_O}if(!document.querySelectorAll("*").forEach){(function(){function patch(what){var querySelectorAll=what.querySelectorAll;what.querySelectorAll=function qSA(css){var result=querySelectorAll.call(this,css);result.forEach=Array.prototype.forEach;return result}}patch(document);patch(Element.prototype)})()}try{document.querySelector(":scope *")}catch(o_O){(function(){var dataScope="data-scope-"+(Math.random()*1e9>>>0);var proto=Element.prototype;var querySelector=proto.querySelector;var querySelectorAll=proto.querySelectorAll;proto.querySelector=function qS(css){return find(this,querySelector,css)};proto.querySelectorAll=function qSA(css){return find(this,querySelectorAll,css)};function find(node,method,css){node.setAttribute(dataScope,null);var result=method.call(node,String(css).replace(/(^|,\s*)(:scope([ >]|$))/g,(function($0,$1,$2,$3){return $1+"["+dataScope+"]"+($3||" ")})));node.removeAttribute(dataScope);return result}})()}})(window);(function(global){"use strict";var DOMMap=global.WeakMap||function(){var counter=0,dispatched=false,drop=false,value;function dispatch(key,ce,shouldDrop){drop=shouldDrop;dispatched=false;value=undefined;key.dispatchEvent(ce)}function Handler(value){this.value=value}Handler.prototype.handleEvent=function handleEvent(e){dispatched=true;if(drop){e.currentTarget.removeEventListener(e.type,this,false)}else{value=this.value}};function DOMMap(){counter++;this.__ce__=new Event("@DOMMap:"+counter+Math.random())}DOMMap.prototype={constructor:DOMMap,"delete":function del(key){return dispatch(key,this.__ce__,true),dispatched},get:function get(key){dispatch(key,this.__ce__,false);var v=value;value=undefined;return v},has:function has(key){return dispatch(key,this.__ce__,false),dispatched},set:function set(key,value){dispatch(key,this.__ce__,true);key.addEventListener(this.__ce__.type,new Handler(value),false);return this}};return DOMMap}();function Dict(){}Dict.prototype=(Object.create||Object)(null);function createEventListener(type,callback,options){function eventListener(e){if(eventListener.once){e.currentTarget.removeEventListener(e.type,callback,eventListener);eventListener.removed=true}if(eventListener.passive){e.preventDefault=createEventListener.preventDefault}if(typeof eventListener.callback==="function"){eventListener.callback.call(this,e)}else if(eventListener.callback){eventListener.callback.handleEvent(e)}if(eventListener.passive){delete e.preventDefault}}eventListener.type=type;eventListener.callback=callback;eventListener.capture=!!options.capture;eventListener.passive=!!options.passive;eventListener.once=!!options.once;eventListener.removed=false;return eventListener}createEventListener.preventDefault=function preventDefault(){};var Event=global.CustomEvent,dE=global.dispatchEvent,aEL=global.addEventListener,rEL=global.removeEventListener,counter=0,increment=function(){counter++},indexOf=[].indexOf||function indexOf(value){var length=this.length;while(length--){if(this[length]===value){break}}return length},getListenerKey=function(options){return"".concat(options.capture?"1":"0",options.passive?"1":"0",options.once?"1":"0")},augment;try{aEL("_",increment,{once:true});dE(new Event("_"));dE(new Event("_"));rEL("_",increment,{once:true})}catch(o_O){}if(counter!==1){(function(){var dm=new DOMMap;function createAEL(aEL){return function addEventListener(type,handler,options){if(options&&typeof options!=="boolean"){var info=dm.get(this),key=getListenerKey(options),i,tmp,wrap;if(!info)dm.set(this,info=new Dict);if(!(type in info))info[type]={handler:[],wrap:[]};tmp=info[type];i=indexOf.call(tmp.handler,handler);if(i<0){i=tmp.handler.push(handler)-1;tmp.wrap[i]=wrap=new Dict}else{wrap=tmp.wrap[i]}if(!(key in wrap)){wrap[key]=createEventListener(type,handler,options);aEL.call(this,type,wrap[key],wrap[key].capture)}}else{aEL.call(this,type,handler,options)}}}function createREL(rEL){return function removeEventListener(type,handler,options){if(options&&typeof options!=="boolean"){var info=dm.get(this),key,i,tmp,wrap;if(info&&type in info){tmp=info[type];i=indexOf.call(tmp.handler,handler);if(-1<i){key=getListenerKey(options);wrap=tmp.wrap[i];if(key in wrap){rEL.call(this,type,wrap[key],wrap[key].capture);delete wrap[key];for(key in wrap)return;tmp.handler.splice(i,1);tmp.wrap.splice(i,1);if(tmp.handler.length===0)delete info[type]}}}}else{rEL.call(this,type,handler,options)}}}augment=function(Constructor){if(!Constructor)return;var proto=Constructor.prototype;proto.addEventListener=createAEL(proto.addEventListener);proto.removeEventListener=createREL(proto.removeEventListener)};if(global.EventTarget){augment(EventTarget)}else{augment(global.Text);augment(global.Element||global.HTMLElement);augment(global.HTMLDocument);augment(global.Window||{prototype:global});augment(global.XMLHttpRequest)}})()}})(window);(function(Proto){"use strict";if(typeof Proto.setAttribute!=="undefined"){function toAttr(prop){return prop.replace(/-[a-z]/g,(function(bit){return bit[1].toUpperCase()}))}Proto.setProperty=function(prop,value){var attr=toAttr(prop);if(!value){return this.removeAttribute(attr)}var str=String(value);return this.setAttribute(attr,str)};Proto.getPropertyValue=function(prop){var attr=toAttr(prop);return this.getAttribute(attr)||null};Proto.removeProperty=function(prop){var attr=toAttr(prop);var value=this.getAttribute(attr);this.removeAttribute(attr);return value}}})(CSSStyleDeclaration.prototype);(function(){"use strict";if(!Function.prototype.bind)(function(){var slice=Array.prototype.slice;Function.prototype.bind=function(){var thatFunc=this,thatArg=arguments[0];var args=slice.call(arguments,1);if(typeof thatFunc!=="function"){throw new TypeError("Function.prototype.bind - "+"what is trying to be bound is not callable")}return function(){var funcArgs=args.concat(slice.call(arguments));return thatFunc.apply(thatArg,funcArgs)}}})();if(!Array.prototype["forEach"]){Array.prototype.forEach=function(callback,thisArg){if(this==null){throw new TypeError("Array.prototype.forEach called on null or undefined")}var T,k;var O=Object(this);var len=O.length>>>0;if(typeof callback!=="function"){throw new TypeError(callback+" is not a function")}if(arguments.length>1){T=thisArg}k=0;while(k<len){var kValue;if(k in O){kValue=O[k];callback.call(T,kValue,k,O)}k++}}}if(!window.Int32Array){window.Int32Array=Array}})();
\ No newline at end of file
+(function(){"use strict";if(!window.Int32Array){window.Int32Array=Array}!function(){function t(){var e=Array.prototype.slice.call(arguments),n=document.createDocumentFragment();e.forEach((function(e){var t=e instanceof Node;n.appendChild(t?e:document.createTextNode(String(e)))})),this.appendChild(n)}function n(){this.parentNode&&this.parentNode.removeChild(this)}[Element.prototype,Document.prototype,DocumentFragment.prototype].forEach((function(e){e.hasOwnProperty("append")||Object.defineProperty(e,"append",{configurable:!0,enumerable:!0,writable:!0,value:t});e.hasOwnProperty("remove")||Object.defineProperty(e,"remove",{configurable:!0,enumerable:!0,writable:!0,value:n})}))}()})();
\ No newline at end of file
diff --git a/tgui/public/tgui.html b/tgui/public/tgui.html
index 5bd21f1b50d..53accdc6c15 100644
--- a/tgui/public/tgui.html
+++ b/tgui/public/tgui.html
@@ -658,6 +658,5 @@
 // Signal tgui that we're ready to receive updates
 Byond.sendMessage('ready');
 </script>
-  
 </body>
 </html>
diff --git a/tgui/tsconfig.json b/tgui/tsconfig.json
index c149d1302a6..9b4c851d971 100644
--- a/tgui/tsconfig.json
+++ b/tgui/tsconfig.json
@@ -15,7 +15,7 @@
     "skipLibCheck": true,
     "strict": false,
     "strictNullChecks": true,
-    "target": "ES3"
+    "target": "ES5"
   },
   "include": ["./*.d.ts", "./packages"]
 }
diff --git a/tgui/webpack.config.js b/tgui/webpack.config.js
index 1bc9f209cbd..d16d404298c 100644
--- a/tgui/webpack.config.js
+++ b/tgui/webpack.config.js
@@ -24,14 +24,13 @@ const createStats = (verbose) => ({
   version: verbose,
 });
 
-// prettier-ignore
 module.exports = (env = {}, argv) => {
   const mode = argv.mode || 'production';
   const bench = env.TGUI_BENCH;
   const config = {
     mode: mode === 'production' ? 'production' : 'development',
     context: path.resolve(__dirname),
-    target: ['web', 'es3', 'browserslist:ie 8'],
+    target: ['web', 'es5', 'browserslist:ie 11'],
     entry: {
       'tgui': ['./packages/tgui-polyfill', './packages/tgui'],
       'tgui-panel': ['./packages/tgui-polyfill', './packages/tgui-panel'],
@@ -137,6 +136,7 @@ module.exports = (env = {}, argv) => {
   if (mode === 'production') {
     const TerserPlugin = require('terser-webpack-plugin');
     config.optimization.minimizer = [
+<<<<<<< HEAD
       new TerserPlugin({
         extractComments: false,
         terserOptions: {
@@ -146,6 +146,11 @@ module.exports = (env = {}, argv) => {
             comments: false,
           },
         },
+=======
+      new EsbuildPlugin({
+        target: 'ie11',
+        css: true,
+>>>>>>> 1a617eacb ([MIRROR] Drops ie8 support [MDB IGNORE] (#25322))
       }),
     ];
   }