diff --git a/libs/es-module-shims.js b/libs/es-module-shims.js
new file mode 100644
index 00000000..96a4bbc8
--- /dev/null
+++ b/libs/es-module-shims.js
@@ -0,0 +1,964 @@
+/* ES Module Shims 1.8.0 */
+(function () {
+
+ const hasWindow = typeof window !== 'undefined';
+ const hasDocument = typeof document !== 'undefined';
+
+ const noop = () => {};
+
+ const optionsScript = hasDocument ? document.querySelector('script[type=esms-options]') : undefined;
+
+ const esmsInitOptions = optionsScript ? JSON.parse(optionsScript.innerHTML) : {};
+ Object.assign(esmsInitOptions, self.esmsInitOptions || {});
+
+ let shimMode = hasDocument ? !!esmsInitOptions.shimMode : true;
+
+ const importHook = globalHook(shimMode && esmsInitOptions.onimport);
+ const resolveHook = globalHook(shimMode && esmsInitOptions.resolve);
+ let fetchHook = esmsInitOptions.fetch ? globalHook(esmsInitOptions.fetch) : fetch;
+ const metaHook = esmsInitOptions.meta ? globalHook(shimMode && esmsInitOptions.meta) : noop;
+
+ const mapOverrides = esmsInitOptions.mapOverrides;
+
+ let nonce = esmsInitOptions.nonce;
+ if (!nonce && hasDocument) {
+ const nonceElement = document.querySelector('script[nonce]');
+ if (nonceElement)
+ nonce = nonceElement.nonce || nonceElement.getAttribute('nonce');
+ }
+
+ const onerror = globalHook(esmsInitOptions.onerror || noop);
+ const onpolyfill = esmsInitOptions.onpolyfill ? globalHook(esmsInitOptions.onpolyfill) : () => {
+ console.log('%c^^ Module TypeError above is polyfilled and can be ignored ^^', 'font-weight:900;color:#391');
+ };
+
+ const { revokeBlobURLs, noLoadEventRetriggers, enforceIntegrity } = esmsInitOptions;
+
+ function globalHook (name) {
+ return typeof name === 'string' ? self[name] : name;
+ }
+
+ const enable = Array.isArray(esmsInitOptions.polyfillEnable) ? esmsInitOptions.polyfillEnable : [];
+ const cssModulesEnabled = enable.includes('css-modules');
+ const jsonModulesEnabled = enable.includes('json-modules');
+
+ const edge = !navigator.userAgentData && !!navigator.userAgent.match(/Edge\/\d+\.\d+/);
+
+ const baseUrl = hasDocument
+ ? document.baseURI
+ : `${location.protocol}//${location.host}${location.pathname.includes('/')
+ ? location.pathname.slice(0, location.pathname.lastIndexOf('/') + 1)
+ : location.pathname}`;
+
+ const createBlob = (source, type = 'text/javascript') => URL.createObjectURL(new Blob([source], { type }));
+ let { skip } = esmsInitOptions;
+ if (Array.isArray(skip)) {
+ const l = skip.map(s => new URL(s, baseUrl).href);
+ skip = s => l.some(i => i[i.length - 1] === '/' && s.startsWith(i) || s === i);
+ }
+ else if (typeof skip === 'string') {
+ const r = new RegExp(skip);
+ skip = s => r.test(s);
+ }
+
+ const eoop = err => setTimeout(() => { throw err });
+
+ const throwError = err => { (self.reportError || hasWindow && window.safari && console.error || eoop)(err), void onerror(err); };
+
+ function fromParent (parent) {
+ return parent ? ` imported from ${parent}` : '';
+ }
+
+ let importMapSrcOrLazy = false;
+
+ function setImportMapSrcOrLazy () {
+ importMapSrcOrLazy = true;
+ }
+
+ // shim mode is determined on initialization, no late shim mode
+ if (!shimMode) {
+ if (document.querySelectorAll('script[type=module-shim],script[type=importmap-shim],link[rel=modulepreload-shim]').length) {
+ shimMode = true;
+ }
+ else {
+ let seenScript = false;
+ for (const script of document.querySelectorAll('script[type=module],script[type=importmap]')) {
+ if (!seenScript) {
+ if (script.type === 'module' && !script.ep)
+ seenScript = true;
+ }
+ else if (script.type === 'importmap' && seenScript) {
+ importMapSrcOrLazy = true;
+ break;
+ }
+ }
+ }
+ }
+
+ const backslashRegEx = /\\/g;
+
+ function isURL (url) {
+ if (url.indexOf(':') === -1) return false;
+ try {
+ new URL(url);
+ return true;
+ }
+ catch (_) {
+ return false;
+ }
+ }
+
+ function resolveUrl (relUrl, parentUrl) {
+ return resolveIfNotPlainOrUrl(relUrl, parentUrl) || (isURL(relUrl) ? relUrl : resolveIfNotPlainOrUrl('./' + relUrl, parentUrl));
+ }
+
+ function resolveIfNotPlainOrUrl (relUrl, parentUrl) {
+ const hIdx = parentUrl.indexOf('#'), qIdx = parentUrl.indexOf('?');
+ if (hIdx + qIdx > -2)
+ parentUrl = parentUrl.slice(0, hIdx === -1 ? qIdx : qIdx === -1 || qIdx > hIdx ? hIdx : qIdx);
+ if (relUrl.indexOf('\\') !== -1)
+ relUrl = relUrl.replace(backslashRegEx, '/');
+ // protocol-relative
+ if (relUrl[0] === '/' && relUrl[1] === '/') {
+ return parentUrl.slice(0, parentUrl.indexOf(':') + 1) + relUrl;
+ }
+ // relative-url
+ else if (relUrl[0] === '.' && (relUrl[1] === '/' || relUrl[1] === '.' && (relUrl[2] === '/' || relUrl.length === 2 && (relUrl += '/')) ||
+ relUrl.length === 1 && (relUrl += '/')) ||
+ relUrl[0] === '/') {
+ const parentProtocol = parentUrl.slice(0, parentUrl.indexOf(':') + 1);
+ // Disabled, but these cases will give inconsistent results for deep backtracking
+ //if (parentUrl[parentProtocol.length] !== '/')
+ // throw new Error('Cannot resolve');
+ // read pathname from parent URL
+ // pathname taken to be part after leading "/"
+ let pathname;
+ if (parentUrl[parentProtocol.length + 1] === '/') {
+ // resolving to a :// so we need to read out the auth and host
+ if (parentProtocol !== 'file:') {
+ pathname = parentUrl.slice(parentProtocol.length + 2);
+ pathname = pathname.slice(pathname.indexOf('/') + 1);
+ }
+ else {
+ pathname = parentUrl.slice(8);
+ }
+ }
+ else {
+ // resolving to :/ so pathname is the /... part
+ pathname = parentUrl.slice(parentProtocol.length + (parentUrl[parentProtocol.length] === '/'));
+ }
+
+ if (relUrl[0] === '/')
+ return parentUrl.slice(0, parentUrl.length - pathname.length - 1) + relUrl;
+
+ // join together and split for removal of .. and . segments
+ // looping the string instead of anything fancy for perf reasons
+ // '../../../../../z' resolved to 'x/y' is just 'z'
+ const segmented = pathname.slice(0, pathname.lastIndexOf('/') + 1) + relUrl;
+
+ const output = [];
+ let segmentIndex = -1;
+ for (let i = 0; i < segmented.length; i++) {
+ // busy reading a segment - only terminate on '/'
+ if (segmentIndex !== -1) {
+ if (segmented[i] === '/') {
+ output.push(segmented.slice(segmentIndex, i + 1));
+ segmentIndex = -1;
+ }
+ continue;
+ }
+ // new segment - check if it is relative
+ else if (segmented[i] === '.') {
+ // ../ segment
+ if (segmented[i + 1] === '.' && (segmented[i + 2] === '/' || i + 2 === segmented.length)) {
+ output.pop();
+ i += 2;
+ continue;
+ }
+ // ./ segment
+ else if (segmented[i + 1] === '/' || i + 1 === segmented.length) {
+ i += 1;
+ continue;
+ }
+ }
+ // it is the start of a new segment
+ while (segmented[i] === '/') i++;
+ segmentIndex = i;
+ }
+ // finish reading out the last segment
+ if (segmentIndex !== -1)
+ output.push(segmented.slice(segmentIndex));
+ return parentUrl.slice(0, parentUrl.length - pathname.length) + output.join('');
+ }
+ }
+
+ function resolveAndComposeImportMap (json, baseUrl, parentMap) {
+ const outMap = { imports: Object.assign({}, parentMap.imports), scopes: Object.assign({}, parentMap.scopes) };
+
+ if (json.imports)
+ resolveAndComposePackages(json.imports, outMap.imports, baseUrl, parentMap);
+
+ if (json.scopes)
+ for (let s in json.scopes) {
+ const resolvedScope = resolveUrl(s, baseUrl);
+ resolveAndComposePackages(json.scopes[s], outMap.scopes[resolvedScope] || (outMap.scopes[resolvedScope] = {}), baseUrl, parentMap);
+ }
+
+ return outMap;
+ }
+
+ function getMatch (path, matchObj) {
+ if (matchObj[path])
+ return path;
+ let sepIndex = path.length;
+ do {
+ const segment = path.slice(0, sepIndex + 1);
+ if (segment in matchObj)
+ return segment;
+ } while ((sepIndex = path.lastIndexOf('/', sepIndex - 1)) !== -1)
+ }
+
+ function applyPackages (id, packages) {
+ const pkgName = getMatch(id, packages);
+ if (pkgName) {
+ const pkg = packages[pkgName];
+ if (pkg === null) return;
+ return pkg + id.slice(pkgName.length);
+ }
+ }
+
+
+ function resolveImportMap (importMap, resolvedOrPlain, parentUrl) {
+ let scopeUrl = parentUrl && getMatch(parentUrl, importMap.scopes);
+ while (scopeUrl) {
+ const packageResolution = applyPackages(resolvedOrPlain, importMap.scopes[scopeUrl]);
+ if (packageResolution)
+ return packageResolution;
+ scopeUrl = getMatch(scopeUrl.slice(0, scopeUrl.lastIndexOf('/')), importMap.scopes);
+ }
+ return applyPackages(resolvedOrPlain, importMap.imports) || resolvedOrPlain.indexOf(':') !== -1 && resolvedOrPlain;
+ }
+
+ function resolveAndComposePackages (packages, outPackages, baseUrl, parentMap) {
+ for (let p in packages) {
+ const resolvedLhs = resolveIfNotPlainOrUrl(p, baseUrl) || p;
+ if ((!shimMode || !mapOverrides) && outPackages[resolvedLhs] && (outPackages[resolvedLhs] !== packages[resolvedLhs])) {
+ throw Error(`Rejected map override "${resolvedLhs}" from ${outPackages[resolvedLhs]} to ${packages[resolvedLhs]}.`);
+ }
+ let target = packages[p];
+ if (typeof target !== 'string')
+ continue;
+ const mapped = resolveImportMap(parentMap, resolveIfNotPlainOrUrl(target, baseUrl) || target, baseUrl);
+ if (mapped) {
+ outPackages[resolvedLhs] = mapped;
+ continue;
+ }
+ console.warn(`Mapping "${p}" -> "${packages[p]}" does not resolve`);
+ }
+ }
+
+ let dynamicImport = !hasDocument && (0, eval)('u=>import(u)');
+
+ let supportsDynamicImport;
+
+ const dynamicImportCheck = hasDocument && new Promise(resolve => {
+ const s = Object.assign(document.createElement('script'), {
+ src: createBlob('self._d=u=>import(u)'),
+ ep: true
+ });
+ s.setAttribute('nonce', nonce);
+ s.addEventListener('load', () => {
+ if (!(supportsDynamicImport = !!(dynamicImport = self._d))) {
+ let err;
+ window.addEventListener('error', _err => err = _err);
+ dynamicImport = (url, opts) => new Promise((resolve, reject) => {
+ const s = Object.assign(document.createElement('script'), {
+ type: 'module',
+ src: createBlob(`import*as m from'${url}';self._esmsi=m`)
+ });
+ err = undefined;
+ s.ep = true;
+ if (nonce)
+ s.setAttribute('nonce', nonce);
+ // Safari is unique in supporting module script error events
+ s.addEventListener('error', cb);
+ s.addEventListener('load', cb);
+ function cb (_err) {
+ document.head.removeChild(s);
+ if (self._esmsi) {
+ resolve(self._esmsi, baseUrl);
+ self._esmsi = undefined;
+ }
+ else {
+ reject(!(_err instanceof Event) && _err || err && err.error || new Error(`Error loading ${opts && opts.errUrl || url} (${s.src}).`));
+ err = undefined;
+ }
+ }
+ document.head.appendChild(s);
+ });
+ }
+ document.head.removeChild(s);
+ delete self._d;
+ resolve();
+ });
+ document.head.appendChild(s);
+ });
+
+ // support browsers without dynamic import support (eg Firefox 6x)
+ let supportsJsonAssertions = false;
+ let supportsCssAssertions = false;
+
+ const supports = hasDocument && HTMLScriptElement.supports;
+
+ let supportsImportMaps = supports && supports.name === 'supports' && supports('importmap');
+ let supportsImportMeta = supportsDynamicImport;
+
+ const importMetaCheck = 'import.meta';
+ const cssModulesCheck = `import"x"assert{type:"css"}`;
+ const jsonModulesCheck = `import"x"assert{type:"json"}`;
+
+ let featureDetectionPromise = Promise.resolve(dynamicImportCheck).then(() => {
+ if (!supportsDynamicImport)
+ return;
+
+ if (!hasDocument)
+ return Promise.all([
+ supportsImportMaps || dynamicImport(createBlob(importMetaCheck)).then(() => supportsImportMeta = true, noop),
+ cssModulesEnabled && dynamicImport(createBlob(cssModulesCheck.replace('x', createBlob('', 'text/css')))).then(() => supportsCssAssertions = true, noop),
+ jsonModulesEnabled && dynamicImport(createBlob(jsonModulescheck.replace('x', createBlob('{}', 'text/json')))).then(() => supportsJsonAssertions = true, noop),
+ ]);
+
+ return new Promise(resolve => {
+ const iframe = document.createElement('iframe');
+ iframe.style.display = 'none';
+ iframe.setAttribute('nonce', nonce);
+ function cb ({ data }) {
+ const isFeatureDetectionMessage = Array.isArray(data) && data[0] === 'esms';
+ if (!isFeatureDetectionMessage) {
+ return;
+ }
+ supportsImportMaps = data[1];
+ supportsImportMeta = data[2];
+ supportsCssAssertions = data[3];
+ supportsJsonAssertions = data[4];
+ resolve();
+ document.head.removeChild(iframe);
+ window.removeEventListener('message', cb, false);
+ }
+ window.addEventListener('message', cb, false);
+
+ const importMapTest = `