diff --git a/static/cash.js b/static/cash.js
new file mode 100644
index 0000000..f83c323
--- /dev/null
+++ b/static/cash.js
@@ -0,0 +1,1237 @@
+(function(){
+"use strict";
+var doc = document;
+var win = window;
+var docEle = doc.documentElement;
+var createElement = doc.createElement.bind(doc);
+var div = createElement('div');
+var table = createElement('table');
+var tbody = createElement('tbody');
+var tr = createElement('tr');
+var isArray = Array.isArray, ArrayPrototype = Array.prototype;
+var concat = ArrayPrototype.concat, filter = ArrayPrototype.filter, indexOf = ArrayPrototype.indexOf, map = ArrayPrototype.map, push = ArrayPrototype.push, slice = ArrayPrototype.slice, some = ArrayPrototype.some, splice = ArrayPrototype.splice;
+var idRe = /^#(?:[\w-]|\\.|[^\x00-\xa0])*$/;
+var classRe = /^\.(?:[\w-]|\\.|[^\x00-\xa0])*$/;
+var htmlRe = /<.+>/;
+var tagRe = /^\w+$/;
+// @require ./variables.ts
+function find(selector, context) {
+ var isFragment = isDocumentFragment(context);
+ return !selector || (!isFragment && !isDocument(context) && !isElement(context))
+ ? []
+ : !isFragment && classRe.test(selector)
+ ? context.getElementsByClassName(selector.slice(1).replace(/\\/g, ''))
+ : !isFragment && tagRe.test(selector)
+ ? context.getElementsByTagName(selector)
+ : context.querySelectorAll(selector);
+}
+// @require ./find.ts
+// @require ./variables.ts
+var Cash = /** @class */ (function () {
+ function Cash(selector, context) {
+ if (!selector)
+ return;
+ if (isCash(selector))
+ return selector;
+ var eles = selector;
+ if (isString(selector)) {
+ var ctx = context || doc;
+ eles = idRe.test(selector) && isDocument(ctx)
+ ? ctx.getElementById(selector.slice(1).replace(/\\/g, ''))
+ : htmlRe.test(selector)
+ ? parseHTML(selector)
+ : isCash(ctx)
+ ? ctx.find(selector)
+ : isString(ctx)
+ ? cash(ctx).find(selector)
+ : find(selector, ctx);
+ if (!eles)
+ return;
+ }
+ else if (isFunction(selector)) {
+ return this.ready(selector); //FIXME: `fn.ready` is not included in `core`, but it's actually a core functionality
+ }
+ if (eles.nodeType || eles === win)
+ eles = [eles];
+ this.length = eles.length;
+ for (var i = 0, l = this.length; i < l; i++) {
+ this[i] = eles[i];
+ }
+ }
+ Cash.prototype.init = function (selector, context) {
+ return new Cash(selector, context);
+ };
+ return Cash;
+}());
+var fn = Cash.prototype;
+var cash = fn.init;
+cash.fn = cash.prototype = fn; // Ensuring that `cash () instanceof cash`
+fn.length = 0;
+fn.splice = splice; // Ensuring a cash collection gets printed as array-like in Chrome's devtools
+if (typeof Symbol === 'function') { // Ensuring a cash collection is iterable
+ fn[Symbol['iterator']] = ArrayPrototype[Symbol['iterator']];
+}
+function isCash(value) {
+ return value instanceof Cash;
+}
+function isWindow(value) {
+ return !!value && value === value.window;
+}
+function isDocument(value) {
+ return !!value && value.nodeType === 9;
+}
+function isDocumentFragment(value) {
+ return !!value && value.nodeType === 11;
+}
+function isElement(value) {
+ return !!value && value.nodeType === 1;
+}
+function isText(value) {
+ return !!value && value.nodeType === 3;
+}
+function isBoolean(value) {
+ return typeof value === 'boolean';
+}
+function isFunction(value) {
+ return typeof value === 'function';
+}
+function isString(value) {
+ return typeof value === 'string';
+}
+function isUndefined(value) {
+ return value === undefined;
+}
+function isNull(value) {
+ return value === null;
+}
+function isNumeric(value) {
+ return !isNaN(parseFloat(value)) && isFinite(value);
+}
+function isPlainObject(value) {
+ if (typeof value !== 'object' || value === null)
+ return false;
+ var proto = Object.getPrototypeOf(value);
+ return proto === null || proto === Object.prototype;
+}
+cash.isWindow = isWindow;
+cash.isFunction = isFunction;
+cash.isArray = isArray;
+cash.isNumeric = isNumeric;
+cash.isPlainObject = isPlainObject;
+function each(arr, callback, _reverse) {
+ if (_reverse) {
+ var i = arr.length;
+ while (i--) {
+ if (callback.call(arr[i], i, arr[i]) === false)
+ return arr;
+ }
+ }
+ else if (isPlainObject(arr)) {
+ var keys = Object.keys(arr);
+ for (var i = 0, l = keys.length; i < l; i++) {
+ var key = keys[i];
+ if (callback.call(arr[key], key, arr[key]) === false)
+ return arr;
+ }
+ }
+ else {
+ for (var i = 0, l = arr.length; i < l; i++) {
+ if (callback.call(arr[i], i, arr[i]) === false)
+ return arr;
+ }
+ }
+ return arr;
+}
+cash.each = each;
+fn.each = function (callback) {
+ return each(this, callback);
+};
+fn.empty = function () {
+ return this.each(function (i, ele) {
+ while (ele.firstChild) {
+ ele.removeChild(ele.firstChild);
+ }
+ });
+};
+function extend() {
+ var sources = [];
+ for (var _i = 0; _i < arguments.length; _i++) {
+ sources[_i] = arguments[_i];
+ }
+ var deep = isBoolean(sources[0]) ? sources.shift() : false;
+ var target = sources.shift();
+ var length = sources.length;
+ if (!target)
+ return {};
+ if (!length)
+ return extend(deep, cash, target);
+ for (var i = 0; i < length; i++) {
+ var source = sources[i];
+ for (var key in source) {
+ if (deep && (isArray(source[key]) || isPlainObject(source[key]))) {
+ if (!target[key] || target[key].constructor !== source[key].constructor)
+ target[key] = new source[key].constructor();
+ extend(deep, target[key], source[key]);
+ }
+ else {
+ target[key] = source[key];
+ }
+ }
+ }
+ return target;
+}
+cash.extend = extend;
+fn.extend = function (plugins) {
+ return extend(fn, plugins);
+};
+// @require ./type_checking.ts
+var splitValuesRe = /\S+/g;
+function getSplitValues(str) {
+ return isString(str) ? str.match(splitValuesRe) || [] : [];
+}
+fn.toggleClass = function (cls, force) {
+ var classes = getSplitValues(cls);
+ var isForce = !isUndefined(force);
+ return this.each(function (i, ele) {
+ if (!isElement(ele))
+ return;
+ each(classes, function (i, c) {
+ if (isForce) {
+ force ? ele.classList.add(c) : ele.classList.remove(c);
+ }
+ else {
+ ele.classList.toggle(c);
+ }
+ });
+ });
+};
+fn.addClass = function (cls) {
+ return this.toggleClass(cls, true);
+};
+fn.removeAttr = function (attr) {
+ var attrs = getSplitValues(attr);
+ return this.each(function (i, ele) {
+ if (!isElement(ele))
+ return;
+ each(attrs, function (i, a) {
+ ele.removeAttribute(a);
+ });
+ });
+};
+function attr(attr, value) {
+ if (!attr)
+ return;
+ if (isString(attr)) {
+ if (arguments.length < 2) {
+ if (!this[0] || !isElement(this[0]))
+ return;
+ var value_1 = this[0].getAttribute(attr);
+ return isNull(value_1) ? undefined : value_1;
+ }
+ if (isUndefined(value))
+ return this;
+ if (isNull(value))
+ return this.removeAttr(attr);
+ return this.each(function (i, ele) {
+ if (!isElement(ele))
+ return;
+ ele.setAttribute(attr, value);
+ });
+ }
+ for (var key in attr) {
+ this.attr(key, attr[key]);
+ }
+ return this;
+}
+fn.attr = attr;
+fn.removeClass = function (cls) {
+ if (arguments.length)
+ return this.toggleClass(cls, false);
+ return this.attr('class', '');
+};
+fn.hasClass = function (cls) {
+ return !!cls && some.call(this, function (ele) { return isElement(ele) && ele.classList.contains(cls); });
+};
+fn.get = function (index) {
+ if (isUndefined(index))
+ return slice.call(this);
+ index = Number(index);
+ return this[index < 0 ? index + this.length : index];
+};
+fn.eq = function (index) {
+ return cash(this.get(index));
+};
+fn.first = function () {
+ return this.eq(0);
+};
+fn.last = function () {
+ return this.eq(-1);
+};
+function text(text) {
+ if (isUndefined(text)) {
+ return this.get().map(function (ele) { return isElement(ele) || isText(ele) ? ele.textContent : ''; }).join('');
+ }
+ return this.each(function (i, ele) {
+ if (!isElement(ele))
+ return;
+ ele.textContent = text;
+ });
+}
+fn.text = text;
+// @require core/type_checking.ts
+// @require core/variables.ts
+function computeStyle(ele, prop, isVariable) {
+ if (!isElement(ele))
+ return;
+ var style = win.getComputedStyle(ele, null);
+ return isVariable ? style.getPropertyValue(prop) || undefined : style[prop] || ele.style[prop];
+}
+// @require ./compute_style.ts
+function computeStyleInt(ele, prop) {
+ return parseInt(computeStyle(ele, prop), 10) || 0;
+}
+// @require css/helpers/compute_style_int.ts
+function getExtraSpace(ele, xAxis) {
+ return computeStyleInt(ele, "border".concat(xAxis ? 'Left' : 'Top', "Width")) + computeStyleInt(ele, "padding".concat(xAxis ? 'Left' : 'Top')) + computeStyleInt(ele, "padding".concat(xAxis ? 'Right' : 'Bottom')) + computeStyleInt(ele, "border".concat(xAxis ? 'Right' : 'Bottom', "Width"));
+}
+// @require css/helpers/compute_style.ts
+var defaultDisplay = {};
+function getDefaultDisplay(tagName) {
+ if (defaultDisplay[tagName])
+ return defaultDisplay[tagName];
+ var ele = createElement(tagName);
+ doc.body.insertBefore(ele, null);
+ var display = computeStyle(ele, 'display');
+ doc.body.removeChild(ele);
+ return defaultDisplay[tagName] = display !== 'none' ? display : 'block';
+}
+// @require css/helpers/compute_style.ts
+function isHidden(ele) {
+ return computeStyle(ele, 'display') === 'none';
+}
+// @require ./cash.ts
+function matches(ele, selector) {
+ var matches = ele && (ele['matches'] || ele['webkitMatchesSelector'] || ele['msMatchesSelector']);
+ return !!matches && !!selector && matches.call(ele, selector);
+}
+// @require ./matches.ts
+// @require ./type_checking.ts
+function getCompareFunction(comparator) {
+ return isString(comparator)
+ ? function (i, ele) { return matches(ele, comparator); }
+ : isFunction(comparator)
+ ? comparator
+ : isCash(comparator)
+ ? function (i, ele) { return comparator.is(ele); }
+ : !comparator
+ ? function () { return false; }
+ : function (i, ele) { return ele === comparator; };
+}
+fn.filter = function (comparator) {
+ var compare = getCompareFunction(comparator);
+ return cash(filter.call(this, function (ele, i) { return compare.call(ele, i, ele); }));
+};
+// @require collection/filter.ts
+function filtered(collection, comparator) {
+ return !comparator ? collection : collection.filter(comparator);
+}
+fn.detach = function (comparator) {
+ filtered(this, comparator).each(function (i, ele) {
+ if (ele.parentNode) {
+ ele.parentNode.removeChild(ele);
+ }
+ });
+ return this;
+};
+var fragmentRe = /^\s*<(\w+)[^>]*>/;
+var singleTagRe = /^<(\w+)\s*\/?>(?:<\/\1>)?$/;
+var containers = {
+ '*': div,
+ tr: tbody,
+ td: tr,
+ th: tr,
+ thead: table,
+ tbody: table,
+ tfoot: table
+};
+//TODO: Create elements inside a document fragment, in order to prevent inline event handlers from firing
+//TODO: Ensure the created elements have the fragment as their parent instead of null, this also ensures we can deal with detatched nodes more reliably
+function parseHTML(html) {
+ if (!isString(html))
+ return [];
+ if (singleTagRe.test(html))
+ return [createElement(RegExp.$1)];
+ var fragment = fragmentRe.test(html) && RegExp.$1;
+ var container = containers[fragment] || containers['*'];
+ container.innerHTML = html;
+ return cash(container.childNodes).detach().get();
+}
+cash.parseHTML = parseHTML;
+fn.has = function (selector) {
+ var comparator = isString(selector)
+ ? function (i, ele) { return find(selector, ele).length; }
+ : function (i, ele) { return ele.contains(selector); };
+ return this.filter(comparator);
+};
+fn.not = function (comparator) {
+ var compare = getCompareFunction(comparator);
+ return this.filter(function (i, ele) { return (!isString(comparator) || isElement(ele)) && !compare.call(ele, i, ele); });
+};
+function pluck(arr, prop, deep, until) {
+ var plucked = [];
+ var isCallback = isFunction(prop);
+ var compare = until && getCompareFunction(until);
+ for (var i = 0, l = arr.length; i < l; i++) {
+ if (isCallback) {
+ var val_1 = prop(arr[i]);
+ if (val_1.length)
+ push.apply(plucked, val_1);
+ }
+ else {
+ var val_2 = arr[i][prop];
+ while (val_2 != null) {
+ if (until && compare(-1, val_2))
+ break;
+ plucked.push(val_2);
+ val_2 = deep ? val_2[prop] : null;
+ }
+ }
+ }
+ return plucked;
+}
+// @require core/pluck.ts
+// @require core/variables.ts
+function getValue(ele) {
+ if (ele.multiple && ele.options)
+ return pluck(filter.call(ele.options, function (option) { return option.selected && !option.disabled && !option.parentNode.disabled; }), 'value');
+ return ele.value || '';
+}
+function val(value) {
+ if (!arguments.length)
+ return this[0] && getValue(this[0]);
+ return this.each(function (i, ele) {
+ var isSelect = ele.multiple && ele.options;
+ if (isSelect || checkableRe.test(ele.type)) {
+ var eleValue_1 = isArray(value) ? map.call(value, String) : (isNull(value) ? [] : [String(value)]);
+ if (isSelect) {
+ each(ele.options, function (i, option) {
+ option.selected = eleValue_1.indexOf(option.value) >= 0;
+ }, true);
+ }
+ else {
+ ele.checked = eleValue_1.indexOf(ele.value) >= 0;
+ }
+ }
+ else {
+ ele.value = isUndefined(value) || isNull(value) ? '' : value;
+ }
+ });
+}
+fn.val = val;
+fn.is = function (comparator) {
+ var compare = getCompareFunction(comparator);
+ return some.call(this, function (ele, i) { return compare.call(ele, i, ele); });
+};
+cash.guid = 1;
+function unique(arr) {
+ return arr.length > 1 ? filter.call(arr, function (item, index, self) { return indexOf.call(self, item) === index; }) : arr;
+}
+cash.unique = unique;
+fn.add = function (selector, context) {
+ return cash(unique(this.get().concat(cash(selector, context).get())));
+};
+fn.children = function (comparator) {
+ return filtered(cash(unique(pluck(this, function (ele) { return ele.children; }))), comparator);
+};
+fn.parent = function (comparator) {
+ return filtered(cash(unique(pluck(this, 'parentNode'))), comparator);
+};
+fn.index = function (selector) {
+ var child = selector ? cash(selector)[0] : this[0];
+ var collection = selector ? this : cash(child).parent().children();
+ return indexOf.call(collection, child);
+};
+fn.closest = function (comparator) {
+ var filtered = this.filter(comparator);
+ if (filtered.length)
+ return filtered;
+ var $parent = this.parent();
+ if (!$parent.length)
+ return filtered;
+ return $parent.closest(comparator);
+};
+fn.siblings = function (comparator) {
+ return filtered(cash(unique(pluck(this, function (ele) { return cash(ele).parent().children().not(ele); }))), comparator);
+};
+fn.find = function (selector) {
+ return cash(unique(pluck(this, function (ele) { return find(selector, ele); })));
+};
+// @require core/variables.ts
+// @require collection/filter.ts
+// @require traversal/find.ts
+var HTMLCDATARe = /^\s*\s*$/g;
+var scriptTypeRe = /^$|^module$|\/(java|ecma)script/i;
+var scriptAttributes = ['type', 'src', 'nonce', 'noModule'];
+function evalScripts(node, doc) {
+ var collection = cash(node);
+ collection.filter('script').add(collection.find('script')).each(function (i, ele) {
+ if (scriptTypeRe.test(ele.type) && docEle.contains(ele)) { // The script type is supported // The element is attached to the DOM // Using `documentElement` for broader browser support
+ var script_1 = createElement('script');
+ script_1.text = ele.textContent.replace(HTMLCDATARe, '');
+ each(scriptAttributes, function (i, attr) {
+ if (ele[attr])
+ script_1[attr] = ele[attr];
+ });
+ doc.head.insertBefore(script_1, null);
+ doc.head.removeChild(script_1);
+ }
+ });
+}
+// @require ./eval_scripts.ts
+function insertElement(anchor, target, left, inside, evaluate) {
+ if (inside) { // prepend/append
+ anchor.insertBefore(target, left ? anchor.firstChild : null);
+ }
+ else { // before/after
+ if (anchor.nodeName === 'HTML') {
+ anchor.parentNode.replaceChild(target, anchor);
+ }
+ else {
+ anchor.parentNode.insertBefore(target, left ? anchor : anchor.nextSibling);
+ }
+ }
+ if (evaluate) {
+ evalScripts(target, anchor.ownerDocument);
+ }
+}
+// @require ./insert_element.ts
+function insertSelectors(selectors, anchors, inverse, left, inside, reverseLoop1, reverseLoop2, reverseLoop3) {
+ each(selectors, function (si, selector) {
+ each(cash(selector), function (ti, target) {
+ each(cash(anchors), function (ai, anchor) {
+ var anchorFinal = inverse ? target : anchor;
+ var targetFinal = inverse ? anchor : target;
+ var indexFinal = inverse ? ti : ai;
+ insertElement(anchorFinal, !indexFinal ? targetFinal : targetFinal.cloneNode(true), left, inside, !indexFinal);
+ }, reverseLoop3);
+ }, reverseLoop2);
+ }, reverseLoop1);
+ return anchors;
+}
+fn.after = function () {
+ return insertSelectors(arguments, this, false, false, false, true, true);
+};
+fn.append = function () {
+ return insertSelectors(arguments, this, false, false, true);
+};
+function html(html) {
+ if (!arguments.length)
+ return this[0] && this[0].innerHTML;
+ if (isUndefined(html))
+ return this;
+ var hasScript = /
+
diff --git a/static/jquery.js b/static/jquery.js
deleted file mode 100644
index 1a86433..0000000
--- a/static/jquery.js
+++ /dev/null
@@ -1,10716 +0,0 @@
-/*!
- * jQuery JavaScript Library v3.7.1
- * https://jquery.com/
- *
- * Copyright OpenJS Foundation and other contributors
- * Released under the MIT license
- * https://jquery.org/license
- *
- * Date: 2023-08-28T13:37Z
- */
-( function( global, factory ) {
-
- "use strict";
-
- if ( typeof module === "object" && typeof module.exports === "object" ) {
-
- // For CommonJS and CommonJS-like environments where a proper `window`
- // is present, execute the factory and get jQuery.
- // For environments that do not have a `window` with a `document`
- // (such as Node.js), expose a factory as module.exports.
- // This accentuates the need for the creation of a real `window`.
- // e.g. var jQuery = require("jquery")(window);
- // See ticket trac-14549 for more info.
- module.exports = global.document ?
- factory( global, true ) :
- function( w ) {
- if ( !w.document ) {
- throw new Error( "jQuery requires a window with a document" );
- }
- return factory( w );
- };
- } else {
- factory( global );
- }
-
-// Pass this if window is not defined yet
-} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
-
-// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
-// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
-// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
-// enough that all such attempts are guarded in a try block.
-"use strict";
-
-var arr = [];
-
-var getProto = Object.getPrototypeOf;
-
-var slice = arr.slice;
-
-var flat = arr.flat ? function( array ) {
- return arr.flat.call( array );
-} : function( array ) {
- return arr.concat.apply( [], array );
-};
-
-
-var push = arr.push;
-
-var indexOf = arr.indexOf;
-
-var class2type = {};
-
-var toString = class2type.toString;
-
-var hasOwn = class2type.hasOwnProperty;
-
-var fnToString = hasOwn.toString;
-
-var ObjectFunctionString = fnToString.call( Object );
-
-var support = {};
-
-var isFunction = function isFunction( obj ) {
-
- // Support: Chrome <=57, Firefox <=52
- // In some browsers, typeof returns "function" for HTML