Index: frontend/node_modules/mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js
===================================================================
--- frontend/node_modules/mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,253 @@
+"use strict";
+
+/* global document */
+/*
+  eslint-disable
+  no-console,
+  func-names
+*/
+
+var normalizeUrl = require("./normalize-url");
+var srcByModuleId = Object.create(null);
+var noDocument = typeof document === "undefined";
+var forEach = Array.prototype.forEach;
+
+/* eslint-disable jsdoc/reject-function-type */
+/**
+ * @param {Function} fn any function
+ * @param {number} time time
+ * @returns {() => void} wrapped function
+ */
+function debounce(fn, time) {
+  var timeout = 0;
+  return function () {
+    // @ts-expect-error
+    var self = this;
+    // eslint-disable-next-line prefer-rest-params
+    var args = arguments;
+    // eslint-disable-next-line func-style
+    var functionCall = function functionCall() {
+      return fn.apply(self, args);
+    };
+    clearTimeout(timeout);
+
+    // @ts-expect-error
+    timeout = setTimeout(functionCall, time);
+  };
+}
+/* eslint-enable jsdoc/reject-function-type */
+
+/**
+ * @returns {void}
+ */
+function noop() {}
+
+/** @typedef {(filename?: string) => string[]} GetScriptSrc */
+
+/**
+ * @param {string | number} moduleId a module id
+ * @returns {GetScriptSrc} current script url
+ */
+function getCurrentScriptUrl(moduleId) {
+  var src = srcByModuleId[moduleId];
+  if (!src) {
+    if (document.currentScript) {
+      src = (/** @type {HTMLScriptElement} */document.currentScript).src;
+    } else {
+      var scripts = document.getElementsByTagName("script");
+      var lastScriptTag = scripts[scripts.length - 1];
+      if (lastScriptTag) {
+        src = lastScriptTag.src;
+      }
+    }
+    srcByModuleId[moduleId] = src;
+  }
+
+  /** @type {GetScriptSrc} */
+  return function (fileMap) {
+    if (!src) {
+      return [];
+    }
+    var splitResult = src.split(/([^\\/]+)\.js$/);
+    var filename = splitResult && splitResult[1];
+    if (!filename) {
+      return [src.replace(".js", ".css")];
+    }
+    if (!fileMap) {
+      return [src.replace(".js", ".css")];
+    }
+    return fileMap.split(",").map(function (mapRule) {
+      var reg = new RegExp("".concat(filename, "\\.js$"), "g");
+      return normalizeUrl(src.replace(reg, "".concat(mapRule.replace(/{fileName}/g, filename), ".css")));
+    });
+  };
+}
+
+/**
+ * @param {string} url URL
+ * @returns {boolean} true when URL can be request, otherwise false
+ */
+function isUrlRequest(url) {
+  // An URL is not an request if
+
+  // It is not http or https
+  if (!/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) {
+    return false;
+  }
+  return true;
+}
+
+/** @typedef {HTMLLinkElement & { isLoaded: boolean, visited: boolean }} HotHTMLLinkElement */
+
+/**
+ * @param {HotHTMLLinkElement} el html link element
+ * @param {string=} url a URL
+ */
+function updateCss(el, url) {
+  if (!url) {
+    if (!el.href) {
+      return;
+    }
+
+    // eslint-disable-next-line
+    url = el.href.split("?")[0];
+  }
+  if (!isUrlRequest(/** @type {string} */url)) {
+    return;
+  }
+  if (el.isLoaded === false) {
+    // We seem to be about to replace a css link that hasn't loaded yet.
+    // We're probably changing the same file more than once.
+    return;
+  }
+
+  // eslint-disable-next-line unicorn/prefer-includes
+  if (!url || !(url.indexOf(".css") > -1)) {
+    return;
+  }
+  el.visited = true;
+  var newEl = /** @type {HotHTMLLinkElement} */
+  el.cloneNode();
+  newEl.isLoaded = false;
+  newEl.addEventListener("load", function () {
+    if (newEl.isLoaded) {
+      return;
+    }
+    newEl.isLoaded = true;
+    if (el.parentNode) {
+      el.parentNode.removeChild(el);
+    }
+  });
+  newEl.addEventListener("error", function () {
+    if (newEl.isLoaded) {
+      return;
+    }
+    newEl.isLoaded = true;
+    if (el.parentNode) {
+      el.parentNode.removeChild(el);
+    }
+  });
+  newEl.href = "".concat(url, "?").concat(Date.now());
+  if (el.parentNode) {
+    if (el.nextSibling) {
+      el.parentNode.insertBefore(newEl, el.nextSibling);
+    } else {
+      el.parentNode.appendChild(newEl);
+    }
+  }
+}
+
+/**
+ * @param {string} href href
+ * @param {string[]} src src
+ * @returns {undefined | string} a reload url
+ */
+function getReloadUrl(href, src) {
+  var ret;
+  href = normalizeUrl(href);
+  src.some(
+  /**
+   * @param {string} url url
+   */
+  // eslint-disable-next-line array-callback-return
+  function (url) {
+    // @ts-expect-error fix me in the next major release
+    // eslint-disable-next-line unicorn/prefer-includes
+    if (href.indexOf(src) > -1) {
+      ret = url;
+    }
+  });
+  return ret;
+}
+
+/**
+ * @param {string[]} src source
+ * @returns {boolean} true when loaded, otherwise false
+ */
+function reloadStyle(src) {
+  var elements = document.querySelectorAll("link");
+  var loaded = false;
+  forEach.call(elements, function (el) {
+    if (!el.href) {
+      return;
+    }
+    var url = getReloadUrl(el.href, src);
+    if (url && !isUrlRequest(url)) {
+      return;
+    }
+    if (el.visited === true) {
+      return;
+    }
+    if (url) {
+      updateCss(el, url);
+      loaded = true;
+    }
+  });
+  return loaded;
+}
+
+/**
+ * @returns {void}
+ */
+function reloadAll() {
+  var elements = document.querySelectorAll("link");
+  forEach.call(elements, function (el) {
+    if (el.visited === true) {
+      return;
+    }
+    updateCss(el);
+  });
+}
+
+/**
+ * @param {number | string} moduleId a module id
+ * @param {{ filename?: string, locals?: boolean }} options options
+ * @returns {() => void} wrapper function
+ */
+module.exports = function (moduleId, options) {
+  if (noDocument) {
+    console.log("no window.document found, will not HMR CSS");
+    return noop;
+  }
+  var getScriptSrc = getCurrentScriptUrl(moduleId);
+
+  /**
+   * @returns {void}
+   */
+  function update() {
+    var src = getScriptSrc(options.filename);
+    var reloaded = reloadStyle(src);
+    if (options.locals) {
+      console.log("[HMR] Detected local css modules. Reload all css");
+      reloadAll();
+      return;
+    }
+    if (reloaded) {
+      console.log("[HMR] css reload %s", src.join(" "));
+    } else {
+      console.log("[HMR] Reload all css");
+      reloadAll();
+    }
+  }
+  return debounce(update, 50);
+};
Index: frontend/node_modules/mini-css-extract-plugin/dist/hmr/normalize-url.js
===================================================================
--- frontend/node_modules/mini-css-extract-plugin/dist/hmr/normalize-url.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/mini-css-extract-plugin/dist/hmr/normalize-url.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,39 @@
+"use strict";
+
+/**
+ * @param {string[]} pathComponents path components
+ * @returns {string} normalized url
+ */
+function normalizeUrlInner(pathComponents) {
+  return pathComponents.reduce(function (accumulator, item) {
+    switch (item) {
+      case "..":
+        accumulator.pop();
+        break;
+      case ".":
+        break;
+      default:
+        accumulator.push(item);
+    }
+    return accumulator;
+  }, /** @type {string[]} */[]).join("/");
+}
+
+/**
+ * @param {string} urlString url string
+ * @returns {string} normalized url string
+ */
+module.exports = function normalizeUrl(urlString) {
+  urlString = urlString.trim();
+  if (/^data:/i.test(urlString)) {
+    return urlString;
+  }
+  var protocol =
+  // eslint-disable-next-line unicorn/prefer-includes
+  urlString.indexOf("//") !== -1 ? "".concat(urlString.split("//")[0], "//") : "";
+  var components = urlString.replace(new RegExp(protocol, "i"), "").split("/");
+  var host = components[0].toLowerCase().replace(/\.$/, "");
+  components[0] = "";
+  var path = normalizeUrlInner(components);
+  return protocol + host + path;
+};
Index: frontend/node_modules/mini-css-extract-plugin/dist/index.js
===================================================================
--- frontend/node_modules/mini-css-extract-plugin/dist/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/mini-css-extract-plugin/dist/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,1046 @@
+"use strict";
+
+const path = require("path");
+const {
+  validate
+} = require("schema-utils");
+const {
+  SyncWaterfallHook
+} = require("tapable");
+const schema = require("./plugin-options.json");
+const {
+  ABSOLUTE_PUBLIC_PATH,
+  AUTO_PUBLIC_PATH,
+  BASE_URI,
+  MODULE_TYPE,
+  SINGLE_DOT_PATH_SEGMENT,
+  compareModulesByIdentifier,
+  compileBooleanMatcher,
+  getUndoPath,
+  trueFn
+} = require("./utils");
+
+/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */
+/** @typedef {import("webpack").Compiler} Compiler */
+/** @typedef {import("webpack").Compilation} Compilation */
+/** @typedef {import("webpack").ChunkGraph} ChunkGraph */
+/** @typedef {import("webpack").Chunk} Chunk */
+/** @typedef {import("webpack").ChunkGroup} ChunkGroup */
+/** @typedef {import("webpack").Module} Module */
+/** @typedef {import("webpack").Dependency} Dependency */
+/** @typedef {import("webpack").sources.Source} Source */
+/** @typedef {import("webpack").Configuration} Configuration */
+/** @typedef {import("webpack").WebpackError} WebpackError */
+/** @typedef {import("webpack").AssetInfo} AssetInfo */
+/** @typedef {import("./loader.js").Dependency} LoaderDependency */
+
+/** @typedef {NonNullable<Required<Configuration>['output']['filename']>} Filename */
+/** @typedef {NonNullable<Required<Configuration>['output']['chunkFilename']>} ChunkFilename */
+
+/**
+ * @typedef {object} LoaderOptions
+ * @property {string | ((resourcePath: string, rootContext: string) => string)=} publicPath public path
+ * @property {boolean=} emit true when need to emit, otherwise false
+ * @property {boolean=} esModule need to generate ES module syntax
+ * @property {string=} layer a layer
+ * @property {boolean=} defaultExport true when need to use default export, otherwise false
+ */
+
+/**
+ * @typedef {object} PluginOptions
+ * @property {Filename=} filename filename
+ * @property {ChunkFilename=} chunkFilename chunk filename
+ * @property {boolean=} ignoreOrder true when need to ignore order, otherwise false
+ * @property {string | ((linkTag: HTMLLinkElement) => void)=} insert link insert place or a custom insert function
+ * @property {Record<string, string>=} attributes link attributes
+ * @property {string | false | "text/css"=} linkType value of a link type attribute
+ * @property {boolean=} runtime true when need to generate runtime code, otherwise false
+ * @property {boolean=} experimentalUseImportModule true when need to use `experimentalUseImportModule` API, otherwise false
+ */
+
+/**
+ * @typedef {object} NormalizedPluginOptions
+ * @property {Filename=} filename filename
+ * @property {ChunkFilename=} chunkFilename chunk filename
+ * @property {boolean} ignoreOrder true when need to ignore order, otherwise false
+ * @property {string | ((linkTag: HTMLLinkElement) => void)=} insert a link insert place or a custom insert function
+ * @property {Record<string, string>=} attributes link attributes
+ * @property {string | false | "text/css"=} linkType value of a link type attribute
+ * @property {boolean} runtime true when need to generate runtime code, otherwise false
+ * @property {boolean=} experimentalUseImportModule true when need to use `experimentalUseImportModule` API, otherwise false
+ */
+
+/**
+ * @typedef {object} RuntimeOptions
+ * @property {string | ((linkTag: HTMLLinkElement) => void)=} insert a link insert place or a custom insert function
+ * @property {string | false | "text/css"} linkType value of a link type attribute
+ * @property {Record<string, string>=} attributes link attributes
+ */
+
+const pluginName = "mini-css-extract-plugin";
+const pluginSymbol = Symbol(pluginName);
+const DEFAULT_FILENAME = "[name].css";
+/**
+ * @type {Set<string>}
+ */
+const TYPES = new Set([MODULE_TYPE]);
+/**
+ * @type {ReturnType<Module["codeGeneration"]>}
+ */
+const CODE_GENERATION_RESULT = {
+  sources: new Map(),
+  runtimeRequirements: new Set()
+};
+
+// eslint-disable-next-line jsdoc/reject-any-type
+/** @typedef {{ context: string | null, identifier: string, identifierIndex: number, content: Buffer, sourceMap?: Buffer, media?: string, supports?: string, layer?: any, assetsInfo?: Map<string, AssetInfo>, assets?: { [key: string]: Source } }} CssModuleDependency */
+/** @typedef {Module & { content: Buffer, media?: string, sourceMap?: Buffer, supports?: string, layer?: string, assets?: { [key: string]: Source }, assetsInfo?: Map<string, AssetInfo> }} CssModule */
+/** @typedef {{ new (dependency: CssModuleDependency): CssModule }} CssModuleConstructor */
+/** @typedef {Dependency & CssModuleDependency} CssDependency */
+/** @typedef {Omit<LoaderDependency, "context">} CssDependencyOptions */
+/** @typedef {{ new (loaderDependency: CssDependencyOptions, context: string | null, identifierIndex: number): CssDependency }} CssDependencyConstructor */
+
+/**
+ * @typedef {object} VarNames
+ * @property {string} tag tag
+ * @property {string} chunkId chunk id
+ * @property {string} href href
+ * @property {string} resolve resolve
+ * @property {string} reject reject
+ */
+
+/**
+ * @typedef {object} MiniCssExtractPluginCompilationHooks
+ * @property {import("tapable").SyncWaterfallHook<[string, VarNames], string>} beforeTagInsert before tag insert hook
+ * @property {SyncWaterfallHook<[string, Chunk]>} linkPreload link preload hook
+ * @property {SyncWaterfallHook<[string, Chunk]>} linkPrefetch link prefetch hook
+ */
+
+/**
+ * @type {WeakMap<Compiler["webpack"], CssModuleConstructor>}
+ */
+const cssModuleCache = new WeakMap();
+/**
+ * @type {WeakMap<Compiler["webpack"], CssDependencyConstructor>}
+ */
+const cssDependencyCache = new WeakMap();
+/**
+ * @type {WeakSet<Compiler["webpack"]>}
+ */
+const registered = new WeakSet();
+
+/** @type {WeakMap<Compilation, MiniCssExtractPluginCompilationHooks>} */
+const compilationHooksMap = new WeakMap();
+class MiniCssExtractPlugin {
+  /**
+   * @param {Compiler["webpack"]} webpack webpack
+   * @returns {CssModuleConstructor} CSS module constructor
+   */
+  static getCssModule(webpack) {
+    /**
+     * Prevent creation of multiple CssModule classes to allow other integrations to get the current CssModule.
+     */
+    if (cssModuleCache.has(webpack)) {
+      return /** @type {CssModuleConstructor} */cssModuleCache.get(webpack);
+    }
+    class CssModule extends webpack.Module {
+      /**
+       * @param {CssModuleDependency} dependency css module dependency
+       */
+      constructor({
+        context,
+        identifier,
+        identifierIndex,
+        content,
+        layer,
+        supports,
+        media,
+        sourceMap,
+        assets,
+        assetsInfo
+      }) {
+        super(MODULE_TYPE, /** @type {string | undefined} */context);
+        this.id = "";
+        this._context = context;
+        this._identifier = identifier;
+        this._identifierIndex = identifierIndex;
+        this.content = content;
+        this.layer = layer;
+        this.supports = supports;
+        this.media = media;
+        this.sourceMap = sourceMap;
+        this.assets = assets;
+        this.assetsInfo = assetsInfo;
+        this._needBuild = true;
+      }
+
+      // no source() so webpack 4 doesn't do add stuff to the bundle
+
+      size() {
+        return this.content.length;
+      }
+      identifier() {
+        return `css|${this._identifier}|${this._identifierIndex}|${this.layer || ""}|${this.supports || ""}|${this.media}}}`;
+      }
+
+      /**
+       * @param {Parameters<Module["readableIdentifier"]>[0]} requestShortener request shortener
+       * @returns {ReturnType<Module["readableIdentifier"]>} readable identifier
+       */
+      readableIdentifier(requestShortener) {
+        return `css ${requestShortener.shorten(this._identifier)}${this._identifierIndex ? ` (${this._identifierIndex})` : ""}${this.layer ? ` (layer ${this.layer})` : ""}${this.supports ? ` (supports ${this.supports})` : ""}${this.media ? ` (media ${this.media})` : ""}`;
+      }
+      getSourceTypes() {
+        return TYPES;
+      }
+      codeGeneration() {
+        return CODE_GENERATION_RESULT;
+      }
+      nameForCondition() {
+        const resource = /** @type {string} */
+        this._identifier.split("!").pop();
+        const idx = resource.indexOf("?");
+        if (idx >= 0) {
+          return resource.slice(0, Math.max(0, idx));
+        }
+        return resource;
+      }
+
+      /**
+       * @param {Module} module a module
+       */
+      updateCacheModule(module) {
+        if (!this.content.equals(/** @type {CssModule} */module.content) || this.layer !== /** @type {CssModule} */module.layer || this.supports !== /** @type {CssModule} */module.supports || this.media !== /** @type {CssModule} */module.media || (this.sourceMap ? !this.sourceMap.equals(/** @type {Uint8Array} * */
+        /** @type {CssModule} */module.sourceMap) : false) || this.assets !== /** @type {CssModule} */module.assets || this.assetsInfo !== /** @type {CssModule} */module.assetsInfo) {
+          this._needBuild = true;
+          this.content = /** @type {CssModule} */module.content;
+          this.layer = /** @type {CssModule} */module.layer;
+          this.supports = /** @type {CssModule} */module.supports;
+          this.media = /** @type {CssModule} */module.media;
+          this.sourceMap = /** @type {CssModule} */module.sourceMap;
+          this.assets = /** @type {CssModule} */module.assets;
+          this.assetsInfo = /** @type {CssModule} */module.assetsInfo;
+        }
+      }
+      needRebuild() {
+        return this._needBuild;
+      }
+
+      /**
+       * @param {Parameters<Module["needBuild"]>[0]} context context info
+       * @param {Parameters<Module["needBuild"]>[1]} callback callback function, returns true, if the module needs a rebuild
+       */
+      needBuild(context, callback) {
+        callback(undefined, this._needBuild);
+      }
+
+      /**
+       * @param {Parameters<Module["build"]>[0]} options options
+       * @param {Parameters<Module["build"]>[1]} compilation compilation
+       * @param {Parameters<Module["build"]>[2]} resolver resolver
+       * @param {Parameters<Module["build"]>[3]} fileSystem file system
+       * @param {Parameters<Module["build"]>[4]} callback callback
+       */
+      build(options, compilation, resolver, fileSystem, callback) {
+        this.buildInfo = {
+          assets: this.assets,
+          assetsInfo: this.assetsInfo,
+          cacheable: true,
+          hash: (/** @type {string} */
+
+          this._computeHash(/** @type {string} */
+          compilation.outputOptions.hashFunction))
+        };
+        this.buildMeta = {};
+        this._needBuild = false;
+        callback();
+      }
+
+      /**
+       * @private
+       * @param {string} hashFunction hash function
+       * @returns {string | Buffer} hash digest
+       */
+      _computeHash(hashFunction) {
+        const hash = webpack.util.createHash(hashFunction);
+        hash.update(this.content);
+        if (this.layer) {
+          hash.update(this.layer);
+        }
+        hash.update(this.supports || "");
+        hash.update(this.media || "");
+        hash.update(this.sourceMap || "");
+        return hash.digest("hex");
+      }
+
+      /**
+       * @param {Parameters<Module["updateHash"]>[0]} hash hash
+       * @param {Parameters<Module["updateHash"]>[1]} context context
+       */
+      updateHash(hash, context) {
+        super.updateHash(hash, context);
+        hash.update(/** @type {string} */
+        /** @type {NonNullable<Module["buildInfo"]>} */
+        this.buildInfo.hash);
+      }
+
+      /**
+       * @param {Parameters<Module["serialize"]>[0]} context serializer context
+       */
+      serialize(context) {
+        const {
+          write
+        } = context;
+        write(this._context);
+        write(this._identifier);
+        write(this._identifierIndex);
+        write(this.content);
+        write(this.layer);
+        write(this.supports);
+        write(this.media);
+        write(this.sourceMap);
+        write(this.assets);
+        write(this.assetsInfo);
+        write(this._needBuild);
+        super.serialize(context);
+      }
+
+      /**
+       * @param {Parameters<Module["deserialize"]>[0]} context deserializer context
+       */
+      deserialize(context) {
+        this._needBuild = context.read();
+        super.deserialize(context);
+      }
+    }
+    cssModuleCache.set(webpack, CssModule);
+    webpack.util.serialization.register(CssModule, path.resolve(__dirname, "CssModule"), null, {
+      serialize(instance, context) {
+        instance.serialize(context);
+      },
+      deserialize(context) {
+        const {
+          read
+        } = context;
+        const contextModule = read();
+        const identifier = read();
+        const identifierIndex = read();
+        const content = read();
+        const layer = read();
+        const supports = read();
+        const media = read();
+        const sourceMap = read();
+        const assets = read();
+        const assetsInfo = read();
+        const dep = new CssModule({
+          context: contextModule,
+          identifier,
+          identifierIndex,
+          content,
+          layer,
+          supports,
+          media,
+          sourceMap,
+          assets,
+          assetsInfo
+        });
+        dep.deserialize(context);
+        return dep;
+      }
+    });
+    return CssModule;
+  }
+
+  /**
+   * @param {Compiler["webpack"]} webpack webpack
+   * @returns {CssDependencyConstructor} CSS dependency constructor
+   */
+  static getCssDependency(webpack) {
+    /**
+     * Prevent creation of multiple CssDependency classes to allow other integrations to get the current CssDependency.
+     */
+    if (cssDependencyCache.has(webpack)) {
+      return /** @type {CssDependencyConstructor} */cssDependencyCache.get(webpack);
+    }
+    class CssDependency extends webpack.Dependency {
+      /**
+       * @param {CssDependencyOptions} loaderDependency loader dependency
+       * @param {string | null} context context
+       * @param {number} identifierIndex identifier index
+       */
+      constructor({
+        identifier,
+        content,
+        layer,
+        supports,
+        media,
+        sourceMap
+      }, context, identifierIndex) {
+        super();
+        this.identifier = identifier;
+        this.identifierIndex = identifierIndex;
+        this.content = content;
+        this.layer = layer;
+        this.supports = supports;
+        this.media = media;
+        this.sourceMap = sourceMap;
+        this.context = context;
+        /** @type {{ [key: string]: Source } | undefined}} */
+        this.assets = undefined;
+        /** @type {Map<string, AssetInfo> | undefined} */
+        this.assetsInfo = undefined;
+      }
+
+      /**
+       * @returns {ReturnType<Dependency["getResourceIdentifier"]>} a resource identifier
+       */
+      getResourceIdentifier() {
+        return `css-module-${this.identifier}-${this.identifierIndex}`;
+      }
+
+      /**
+       * @returns {ReturnType<Dependency["getModuleEvaluationSideEffectsState"]>} side effect state
+       */
+      getModuleEvaluationSideEffectsState() {
+        return webpack.ModuleGraphConnection.TRANSITIVE_ONLY;
+      }
+
+      /**
+       * @param {Parameters<Dependency["serialize"]>[0]} context serializer context
+       */
+      serialize(context) {
+        const {
+          write
+        } = context;
+        write(this.identifier);
+        write(this.content);
+        write(this.layer);
+        write(this.supports);
+        write(this.media);
+        write(this.sourceMap);
+        write(this.context);
+        write(this.identifierIndex);
+        write(this.assets);
+        write(this.assetsInfo);
+        super.serialize(context);
+      }
+
+      /**
+       * @param {Parameters<Dependency["deserialize"]>[0]} context deserializer context
+       */
+      deserialize(context) {
+        super.deserialize(context);
+      }
+    }
+    cssDependencyCache.set(webpack, CssDependency);
+    webpack.util.serialization.register(CssDependency, path.resolve(__dirname, "CssDependency"), null, {
+      serialize(instance, context) {
+        instance.serialize(context);
+      },
+      deserialize(context) {
+        const {
+          read
+        } = context;
+        const dep = new CssDependency({
+          identifier: read(),
+          content: read(),
+          layer: read(),
+          supports: read(),
+          media: read(),
+          sourceMap: read()
+        }, read(), read());
+        const assets = read();
+        const assetsInfo = read();
+        dep.assets = assets;
+        dep.assetsInfo = assetsInfo;
+        dep.deserialize(context);
+        return dep;
+      }
+    });
+    return CssDependency;
+  }
+
+  /**
+   * Returns all hooks for the given compilation
+   * @param {Compilation} compilation the compilation
+   * @returns {MiniCssExtractPluginCompilationHooks} hooks
+   */
+  static getCompilationHooks(compilation) {
+    let hooks = compilationHooksMap.get(compilation);
+    if (!hooks) {
+      hooks = {
+        beforeTagInsert: new SyncWaterfallHook(["source", "varNames"], "string"),
+        linkPreload: new SyncWaterfallHook(["source", "chunk"]),
+        linkPrefetch: new SyncWaterfallHook(["source", "chunk"])
+      };
+      compilationHooksMap.set(compilation, hooks);
+    }
+    return hooks;
+  }
+
+  /**
+   * @param {PluginOptions=} options options
+   */
+  constructor(options = {}) {
+    validate(/** @type {Schema} */schema, options, {
+      baseDataPath: "options"
+    });
+
+    /**
+     * @private
+     * @type {WeakMap<Chunk, Set<CssModule>>}
+     */
+    this._sortedModulesCache = new WeakMap();
+
+    /**
+     * @private
+     * @type {NormalizedPluginOptions}
+     */
+    this.options = {
+      ignoreOrder: false,
+      // TODO remove in the next major release
+      experimentalUseImportModule: undefined,
+      runtime: true,
+      ...options
+    };
+
+    /**
+     * @private
+     * @type {RuntimeOptions}
+     */
+    this.runtimeOptions = {
+      insert: options.insert,
+      linkType:
+      // Todo in next major release set default to "false"
+      typeof options.linkType === "boolean" && /** @type {boolean} */options.linkType === true || typeof options.linkType === "undefined" ? "text/css" : options.linkType,
+      attributes: options.attributes
+    };
+  }
+
+  /**
+   * @param {Compiler} compiler compiler
+   */
+  apply(compiler) {
+    // Finally normalize filenames based on compiler options
+    const normalizedFilename = this.options.filename || compiler.options.output.cssFilename || DEFAULT_FILENAME;
+    let normalizedChunkFilename = this.options.chunkFilename || compiler.options.output.cssChunkFilename;
+    if (!normalizedChunkFilename) {
+      if (typeof normalizedFilename !== "function") {
+        const hasName = /** @type {string} */normalizedFilename.includes("[name]");
+        const hasId = /** @type {string} */normalizedFilename.includes("[id]");
+        const hasChunkHash = /** @type {string} */
+        normalizedFilename.includes("[chunkhash]");
+        const hasContentHash = /** @type {string} */
+        normalizedFilename.includes("[contenthash]");
+
+        // Anything changing depending on chunk is fine
+        if (hasChunkHash || hasContentHash || hasName || hasId) {
+          normalizedChunkFilename = normalizedFilename;
+        } else {
+          // Otherwise prefix "[id]." in front of the basename to make it changing
+          normalizedChunkFilename = /** @type {string} */
+          normalizedFilename.replace(/(^|\/)([^/]*(?:\?|$))/, "$1[id].$2");
+        }
+      } else {
+        normalizedChunkFilename = "[id].css";
+      }
+    }
+    const {
+      webpack
+    } = compiler;
+    if (this.options.experimentalUseImportModule && typeof (/** @type {Compiler["options"]["experiments"] & { executeModule?: boolean }} */
+    compiler.options.experiments.executeModule) === "undefined") {
+      /** @type {Compiler["options"]["experiments"] & { executeModule?: boolean }} */
+
+      // @ts-expect-error TODO remove in the next major release
+      compiler.options.experiments.executeModule = true;
+    }
+
+    // TODO bug in webpack, remove it after it will be fixed
+    // webpack tries to `require` loader firstly when serializer doesn't found
+    if (!registered.has(webpack)) {
+      registered.add(webpack);
+      webpack.util.serialization.registerLoader(/^mini-css-extract-plugin\//, trueFn);
+    }
+    const {
+      splitChunks
+    } = compiler.options.optimization;
+    if (splitChunks && /** @type {string[]} */splitChunks.defaultSizeTypes.includes("...")) {
+      /** @type {string[]} */
+      splitChunks.defaultSizeTypes.push(MODULE_TYPE);
+    }
+    const CssModule = MiniCssExtractPlugin.getCssModule(webpack);
+    const CssDependency = MiniCssExtractPlugin.getCssDependency(webpack);
+    const {
+      NormalModule
+    } = compiler.webpack;
+    compiler.hooks.compilation.tap(pluginName, compilation => {
+      const {
+        loader: normalModuleHook
+      } = NormalModule.getCompilationHooks(compilation);
+      normalModuleHook.tap(pluginName,
+      /**
+       * @param {object} loaderContext loader context
+       */
+      loaderContext => {
+        /** @type {object & { [pluginSymbol]: { experimentalUseImportModule: boolean | undefined } }} */
+        loaderContext[pluginSymbol] = {
+          experimentalUseImportModule: this.options.experimentalUseImportModule
+        };
+      });
+    });
+    compiler.hooks.thisCompilation.tap(pluginName, compilation => {
+      class CssModuleFactory {
+        /**
+         * @param {{ dependencies: Dependency[] }} dependencies
+         * @param {(err?: null | Error, result?: CssModule) => void} callback
+         */
+
+        create({
+          dependencies: [dependency]
+        }, callback) {
+          callback(undefined, new CssModule(/** @type {CssDependency} */dependency));
+        }
+      }
+      compilation.dependencyFactories.set(CssDependency,
+      // @ts-expect-error TODO fix in the next major release and fix using `CssModuleFactory extends webpack.ModuleFactory`
+      new CssModuleFactory());
+      class CssDependencyTemplate {
+        apply() {}
+      }
+      compilation.dependencyTemplates.set(CssDependency, new CssDependencyTemplate());
+      compilation.hooks.renderManifest.tap(pluginName,
+      /**
+       * @param {ReturnType<Compilation["getRenderManifest"]>} result result
+       * @param {Parameters<Compilation["getRenderManifest"]>[0]} chunk chunk
+       * @returns {ReturnType<Compilation["getRenderManifest"]>} a rendered manifest
+       */
+      (result, {
+        chunk
+      }) => {
+        const {
+          chunkGraph
+        } = compilation;
+        const {
+          HotUpdateChunk
+        } = webpack;
+
+        // We don't need hot update chunks for css
+        // We will use the real asset instead to update
+        if (chunk instanceof HotUpdateChunk) {
+          return result;
+        }
+        const renderedModules = /** @type {CssModule[]} */
+
+        [...this.getChunkModules(chunk, chunkGraph)].filter(module => module.type === MODULE_TYPE);
+        const filenameTemplate = /** @type {string} */
+
+        chunk.canBeInitial() ? normalizedFilename : normalizedChunkFilename;
+        if (renderedModules.length > 0) {
+          result.push({
+            render: () => this.renderContentAsset(compiler, compilation, chunk, renderedModules, compilation.runtimeTemplate.requestShortener, filenameTemplate, {
+              contentHashType: MODULE_TYPE,
+              chunk
+            }),
+            filenameTemplate,
+            pathOptions: {
+              chunk,
+              contentHashType: MODULE_TYPE
+            },
+            identifier: `${pluginName}.${chunk.id}`,
+            hash: chunk.contentHash[MODULE_TYPE]
+          });
+        }
+        return result;
+      });
+      compilation.hooks.contentHash.tap(pluginName, chunk => {
+        const {
+          outputOptions,
+          chunkGraph
+        } = compilation;
+        const modules = this.sortModules(compilation, chunk, /** @type {CssModule[]} */
+        chunkGraph.getChunkModulesIterableBySourceType(chunk, MODULE_TYPE), compilation.runtimeTemplate.requestShortener);
+        if (modules && modules.size > 0) {
+          const {
+            hashFunction,
+            hashDigest,
+            hashDigestLength
+          } = outputOptions;
+          const {
+            createHash
+          } = compiler.webpack.util;
+          const hash = createHash(/** @type {string} */hashFunction);
+          for (const m of modules) {
+            hash.update(chunkGraph.getModuleHash(m, chunk.runtime));
+          }
+          chunk.contentHash[MODULE_TYPE] = /** @type {string} */
+          hash.digest(hashDigest).slice(0, Math.max(0, /** @type {number} */hashDigestLength));
+        }
+      });
+
+      // All the code below is dedicated to the runtime and can be skipped when the `runtime` option is `false`
+      if (!this.options.runtime) {
+        return;
+      }
+      const {
+        Template,
+        RuntimeGlobals,
+        RuntimeModule,
+        runtime
+      } = webpack;
+
+      /**
+       * @param {Chunk} mainChunk
+       * @param {Compilation} compilation
+       * @returns {Record<string, number>}
+       */
+
+      const getCssChunkObject = (mainChunk, compilation) => {
+        /** @type {Record<string, number>} */
+        const obj = {};
+        const {
+          chunkGraph
+        } = compilation;
+        for (const chunk of mainChunk.getAllAsyncChunks()) {
+          const modules = chunkGraph.getOrderedChunkModulesIterable(chunk, compareModulesByIdentifier);
+          for (const module of modules) {
+            if (module.type === MODULE_TYPE) {
+              obj[(/** @type {string} */chunk.id)] = 1;
+              break;
+            }
+          }
+        }
+        return obj;
+      };
+
+      /**
+       * @param {Chunk} chunk chunk
+       * @param {ChunkGraph} chunkGraph chunk graph
+       * @returns {boolean} true, when the chunk has css
+       */
+      function chunkHasCss(chunk, chunkGraph) {
+        // this function replace:
+        // const chunkHasCss = require("webpack/lib/css/CssModulesPlugin").chunkHasCss;
+        return Boolean(chunkGraph.getChunkModulesIterableBySourceType(chunk, "css/mini-extract"));
+      }
+      class CssLoadingRuntimeModule extends RuntimeModule {
+        /**
+         * @param {Set<string>} runtimeRequirements runtime Requirements
+         * @param {RuntimeOptions} runtimeOptions runtime options
+         */
+        constructor(runtimeRequirements, runtimeOptions) {
+          super("css loading", 10);
+          this.runtimeRequirements = runtimeRequirements;
+          this.runtimeOptions = runtimeOptions;
+        }
+        generate() {
+          const {
+            chunkGraph,
+            chunk,
+            runtimeRequirements
+          } = this;
+          const {
+            runtimeTemplate,
+            outputOptions: {
+              crossOriginLoading
+            }
+          } = /** @type {Compilation} */this.compilation;
+          const chunkMap = getCssChunkObject(/** @type {Chunk} */chunk, /** @type {Compilation} */this.compilation);
+          const withLoading = runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) && Object.keys(chunkMap).length > 0;
+          const withHmr = runtimeRequirements.has(RuntimeGlobals.hmrDownloadUpdateHandlers);
+          if (!withLoading && !withHmr) {
+            return "";
+          }
+          const conditionMap = /** @type {ChunkGraph} */chunkGraph.getChunkConditionMap(/** @type {Chunk} */chunk, chunkHasCss);
+          const hasCssMatcher = compileBooleanMatcher(conditionMap);
+          const withPrefetch = runtimeRequirements.has(RuntimeGlobals.prefetchChunkHandlers);
+          const withPreload = runtimeRequirements.has(RuntimeGlobals.preloadChunkHandlers);
+          const {
+            linkPreload,
+            linkPrefetch
+          } = MiniCssExtractPlugin.getCompilationHooks(compilation);
+          return Template.asString(['if (typeof document === "undefined") return;', `var createStylesheet = ${runtimeTemplate.basicFunction("chunkId, fullhref, oldTag, resolve, reject", ['var linkTag = document.createElement("link");', this.runtimeOptions.attributes ? Template.asString(Object.entries(this.runtimeOptions.attributes).map(entry => {
+            const [key, value] = entry;
+            return `linkTag.setAttribute(${JSON.stringify(key)}, ${JSON.stringify(value)});`;
+          })) : "", 'linkTag.rel = "stylesheet";', this.runtimeOptions.linkType ? `linkTag.type = ${JSON.stringify(this.runtimeOptions.linkType)};` : "", `if (${RuntimeGlobals.scriptNonce}) {`, Template.indent(`linkTag.nonce = ${RuntimeGlobals.scriptNonce};`), "}", `var onLinkComplete = ${runtimeTemplate.basicFunction("event", ["// avoid mem leaks.", "linkTag.onerror = linkTag.onload = null;", "if (event.type === 'load') {", Template.indent(["resolve();"]), "} else {", Template.indent(["var errorType = event && event.type;", "var realHref = event && event.target && event.target.href || fullhref;", 'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + errorType + ": " + realHref + ")");', 'err.name = "ChunkLoadError";',
+          // TODO remove `code` in the future major release to align with webpack
+          'err.code = "CSS_CHUNK_LOAD_FAILED";', "err.type = errorType;", "err.request = realHref;", "if (linkTag.parentNode) linkTag.parentNode.removeChild(linkTag)", "reject(err);"]), "}"])}`, "linkTag.onerror = linkTag.onload = onLinkComplete;", "linkTag.href = fullhref;", crossOriginLoading ? Template.asString(["if (linkTag.href.indexOf(window.location.origin + '/') !== 0) {", Template.indent(`linkTag.crossOrigin = ${JSON.stringify(crossOriginLoading)};`), "}"]) : "", MiniCssExtractPlugin.getCompilationHooks(compilation).beforeTagInsert.call("", {
+            tag: "linkTag",
+            chunkId: "chunkId",
+            href: "fullhref",
+            resolve: "resolve",
+            reject: "reject"
+          }) || "", typeof this.runtimeOptions.insert !== "undefined" ? typeof this.runtimeOptions.insert === "function" ? `(${this.runtimeOptions.insert.toString()})(linkTag)` : Template.asString([`var target = document.querySelector("${this.runtimeOptions.insert}");`, "target.parentNode.insertBefore(linkTag, target.nextSibling);"]) : Template.asString(["if (oldTag) {", Template.indent(["oldTag.parentNode.insertBefore(linkTag, oldTag.nextSibling);"]), "} else {", Template.indent(["document.head.appendChild(linkTag);"]), "}"]), "return linkTag;"])};`, `var findStylesheet = ${runtimeTemplate.basicFunction("href, fullhref", ['var existingLinkTags = document.getElementsByTagName("link");', "for(var i = 0; i < existingLinkTags.length; i++) {", Template.indent(["var tag = existingLinkTags[i];", 'var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");', 'if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return tag;']), "}", 'var existingStyleTags = document.getElementsByTagName("style");', "for(var i = 0; i < existingStyleTags.length; i++) {", Template.indent(["var tag = existingStyleTags[i];", 'var dataHref = tag.getAttribute("data-href");', "if(dataHref === href || dataHref === fullhref) return tag;"]), "}"])};`, `var loadStylesheet = ${runtimeTemplate.basicFunction("chunkId", `return new Promise(${runtimeTemplate.basicFunction("resolve, reject", [`var href = ${RuntimeGlobals.require}.miniCssF(chunkId);`, `var fullhref = ${RuntimeGlobals.publicPath} + href;`, "if(findStylesheet(href, fullhref)) return resolve();", "createStylesheet(chunkId, fullhref, null, resolve, reject);"])});`)}`, withLoading ? Template.asString(["// object to store loaded CSS chunks", "var installedCssChunks = {", Template.indent(/** @type {string[]} */
+          (/** @type {Chunk} */chunk.ids).map(id => `${JSON.stringify(id)}: 0`).join(",\n")), "};", "", `${RuntimeGlobals.ensureChunkHandlers}.miniCss = ${runtimeTemplate.basicFunction("chunkId, promises", [`var cssChunks = ${JSON.stringify(chunkMap)};`, "if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);", "else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {", Template.indent([`promises.push(installedCssChunks[chunkId] = loadStylesheet(chunkId).then(${runtimeTemplate.basicFunction("", "installedCssChunks[chunkId] = 0;")}, ${runtimeTemplate.basicFunction("e", ["delete installedCssChunks[chunkId];", "throw e;"])}));`]), "}"])};`]) : "// no chunk loading", "", withHmr ? Template.asString(["var oldTags = [];", "var newTags = [];", `var applyHandler = ${runtimeTemplate.basicFunction("options", [`return { dispose: ${runtimeTemplate.basicFunction("", ["for(var i = 0; i < oldTags.length; i++) {", Template.indent(["var oldTag = oldTags[i];", "if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);"]), "}", "oldTags.length = 0;"])}, apply: ${runtimeTemplate.basicFunction("", ['for(var i = 0; i < newTags.length; i++) newTags[i].rel = "stylesheet";', "newTags.length = 0;"])} };`])}`, `${RuntimeGlobals.hmrDownloadUpdateHandlers}.miniCss = ${runtimeTemplate.basicFunction("chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList", ["applyHandlers.push(applyHandler);", `chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [`var href = ${RuntimeGlobals.require}.miniCssF(chunkId);`, `var fullhref = ${RuntimeGlobals.publicPath} + href;`, "var oldTag = findStylesheet(href, fullhref);", "if(!oldTag) return;", `promises.push(new Promise(${runtimeTemplate.basicFunction("resolve, reject", [`var tag = createStylesheet(chunkId, fullhref, oldTag, ${runtimeTemplate.basicFunction("", ['tag.as = "style";', 'tag.rel = "preload";', "resolve();"])}, reject);`, "oldTags.push(oldTag);", "newTags.push(tag);"])}));`])});`])}`]) : "// no hmr", "", withPrefetch && withLoading && hasCssMatcher !== false ? `${RuntimeGlobals.prefetchChunkHandlers}.miniCss = ${runtimeTemplate.basicFunction("chunkId", [`if((!${RuntimeGlobals.hasOwnProperty}(installedCssChunks, chunkId) || installedCssChunks[chunkId] === undefined) && ${hasCssMatcher === true ? "true" : hasCssMatcher("chunkId")}) {`, Template.indent(["installedCssChunks[chunkId] = null;", linkPrefetch.call(Template.asString(["var link = document.createElement('link');", crossOriginLoading ? `link.crossOrigin = ${JSON.stringify(crossOriginLoading)};` : "", `if (${RuntimeGlobals.scriptNonce}) {`, Template.indent(`link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`), "}", 'link.rel = "prefetch";', 'link.as = "style";', `link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.require}.miniCssF(chunkId);`]), /** @type {Chunk} */chunk), "document.head.appendChild(link);"]), "}"])};` : "// no prefetching", "", withPreload && withLoading && hasCssMatcher !== false ? `${RuntimeGlobals.preloadChunkHandlers}.miniCss = ${runtimeTemplate.basicFunction("chunkId", [`if((!${RuntimeGlobals.hasOwnProperty}(installedCssChunks, chunkId) || installedCssChunks[chunkId] === undefined) && ${hasCssMatcher === true ? "true" : hasCssMatcher("chunkId")}) {`, Template.indent(["installedCssChunks[chunkId] = null;", linkPreload.call(Template.asString(["var link = document.createElement('link');", "link.charset = 'utf-8';", `if (${RuntimeGlobals.scriptNonce}) {`, Template.indent(`link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`), "}", 'link.rel = "preload";', 'link.as = "style";', `link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.require}.miniCssF(chunkId);`, crossOriginLoading ? crossOriginLoading === "use-credentials" ? 'link.crossOrigin = "use-credentials";' : Template.asString(["if (link.href.indexOf(window.location.origin + '/') !== 0) {", Template.indent(`link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`), "}"]) : ""]), /** @type {Chunk} */chunk), "document.head.appendChild(link);"]), "}"])};` : "// no preloaded"]);
+        }
+      }
+      const enabledChunks = new WeakSet();
+
+      /**
+       * @param {Chunk} chunk chunk
+       * @param {Set<string>} set set with runtime requirement
+       */
+      const handler = (chunk, set) => {
+        if (enabledChunks.has(chunk)) {
+          return;
+        }
+        enabledChunks.add(chunk);
+        if (typeof normalizedChunkFilename === "string" && /\[(full)?hash(:\d+)?\]/.test(normalizedChunkFilename)) {
+          set.add(RuntimeGlobals.getFullHash);
+        }
+        set.add(RuntimeGlobals.publicPath);
+        compilation.addRuntimeModule(chunk, new runtime.GetChunkFilenameRuntimeModule(MODULE_TYPE, "mini-css", `${RuntimeGlobals.require}.miniCssF`,
+        /**
+         * @param {Chunk} referencedChunk a referenced chunk
+         * @returns {ReturnType<import("webpack").runtime.GetChunkFilenameRuntimeModule["getFilenameForChunk"]>} a template value
+         */
+        referencedChunk => {
+          if (!referencedChunk.contentHash[MODULE_TYPE]) {
+            return false;
+          }
+          return referencedChunk.canBeInitial() ? (/** @type {Filename} */normalizedFilename) : (/** @type {ChunkFilename} */normalizedChunkFilename);
+        }, set.has(RuntimeGlobals.hmrDownloadUpdateHandlers)));
+        compilation.addRuntimeModule(chunk, new CssLoadingRuntimeModule(set, this.runtimeOptions));
+      };
+      compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.ensureChunkHandlers).tap(pluginName, handler);
+      compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.hmrDownloadUpdateHandlers).tap(pluginName, handler);
+      compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.prefetchChunkHandlers).tap(pluginName, handler);
+      compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.preloadChunkHandlers).tap(pluginName, handler);
+    });
+  }
+
+  /**
+   * @private
+   * @param {Chunk} chunk chunk
+   * @param {ChunkGraph} chunkGraph chunk graph
+   * @returns {Iterable<Module>} modules
+   */
+  getChunkModules(chunk, chunkGraph) {
+    return typeof chunkGraph !== "undefined" ? chunkGraph.getOrderedChunkModulesIterable(chunk, compareModulesByIdentifier) : chunk.modulesIterable;
+  }
+
+  /**
+   * @private
+   * @param {Compilation} compilation compilation
+   * @param {Chunk} chunk chunk
+   * @param {CssModule[]} modules modules
+   * @param {Compilation["requestShortener"]} requestShortener request shortener
+   * @returns {Set<CssModule>} css modules
+   */
+  sortModules(compilation, chunk, modules, requestShortener) {
+    let usedModules = this._sortedModulesCache.get(chunk);
+    if (usedModules || !modules) {
+      return /** @type {Set<CssModule>} */usedModules;
+    }
+
+    /** @type {CssModule[]} */
+    const modulesList = [...modules];
+    // Store dependencies for modules
+    /** @type {Map<CssModule, Set<CssModule>>} */
+    const moduleDependencies = new Map(modulesList.map(m => [m, (/** @type {Set<CssModule>} */
+    new Set())]));
+    /** @type {Map<CssModule, Map<CssModule, Set<ChunkGroup>>>} */
+    const moduleDependenciesReasons = new Map(modulesList.map(m => [m, new Map()]));
+    // Get ordered list of modules per chunk group
+    // This loop also gathers dependencies from the ordered lists
+    // Lists are in reverse order to allow to use Array.pop()
+    /** @type {CssModule[][]} */
+    const modulesByChunkGroup = Array.from(chunk.groupsIterable, chunkGroup => {
+      const sortedModules = modulesList.map(module => ({
+        module,
+        index: chunkGroup.getModulePostOrderIndex(module)
+      })).filter(item => item.index !== undefined).sort((a, b) => /** @type {number} */b.index - (/** @type {number} */a.index)).map(item => item.module);
+      for (let i = 0; i < sortedModules.length; i++) {
+        const set = moduleDependencies.get(sortedModules[i]);
+        const reasons = /** @type {Map<CssModule, Set<ChunkGroup>>} */
+        moduleDependenciesReasons.get(sortedModules[i]);
+        for (let j = i + 1; j < sortedModules.length; j++) {
+          const module = sortedModules[j];
+
+          /** @type {Set<CssModule>} */
+          set.add(module);
+          const reason = reasons.get(module) || (/** @type {Set<ChunkGroup>} */new Set());
+          reason.add(chunkGroup);
+          reasons.set(module, reason);
+        }
+      }
+      return sortedModules;
+    });
+
+    // set with already included modules in correct order
+    usedModules = new Set();
+
+    /**
+     * @param {CssModule} m a css module
+     * @returns {boolean} true when module unused, otherwise false
+     */
+    const unusedModulesFilter = m => !(/** @type {Set<CssModule>} */usedModules.has(m));
+    while (usedModules.size < modulesList.length) {
+      let success = false;
+      let bestMatch;
+      let bestMatchDeps;
+
+      // get first module where dependencies are fulfilled
+      for (const list of modulesByChunkGroup) {
+        // skip and remove already added modules
+        while (list.length > 0 && usedModules.has(list[list.length - 1])) {
+          list.pop();
+        }
+
+        // skip empty lists
+        if (list.length !== 0) {
+          const module = list[list.length - 1];
+          const deps = /** @type {Set<CssModule>} */
+          moduleDependencies.get(module);
+          // determine dependencies that are not yet included
+          const failedDeps = [...deps].filter(unusedModulesFilter);
+
+          // store best match for fallback behavior
+          if (!bestMatchDeps || bestMatchDeps.length > failedDeps.length) {
+            bestMatch = list;
+            bestMatchDeps = failedDeps;
+          }
+          if (failedDeps.length === 0) {
+            // use this module and remove it from list
+            usedModules.add(/** @type {CssModule} */list.pop());
+            success = true;
+            break;
+          }
+        }
+      }
+      if (!success) {
+        // no module found => there is a conflict
+        // use list with fewest failed deps
+        // and emit a warning
+        const fallbackModule = /** @type {CssModule[]} */bestMatch.pop();
+        if (!this.options.ignoreOrder) {
+          const reasons = moduleDependenciesReasons.get(/** @type {CssModule} */fallbackModule);
+          compilation.warnings.push(/** @type {WebpackError} */
+
+          new Error([`chunk ${chunk.name || chunk.id} [${pluginName}]`, "Conflicting order. Following module has been added:", ` * ${ /** @type {CssModule} */fallbackModule.readableIdentifier(requestShortener)}`, "despite it was not able to fulfill desired ordering with these modules:", ... /** @type {CssModule[]} */bestMatchDeps.map(m => {
+            const goodReasonsMap = moduleDependenciesReasons.get(m);
+            const goodReasons = goodReasonsMap && goodReasonsMap.get(/** @type {CssModule} */fallbackModule);
+            const failedChunkGroups = Array.from(/** @type {Set<ChunkGroup>} */
+
+            /** @type {Map<CssModule, Set<ChunkGroup>>} */
+            reasons.get(m), cg => cg.name).join(", ");
+            const goodChunkGroups = goodReasons && Array.from(goodReasons, cg => cg.name).join(", ");
+            return [` * ${m.readableIdentifier(requestShortener)}`, `   - couldn't fulfill desired order of chunk group(s) ${failedChunkGroups}`, goodChunkGroups && `   - while fulfilling desired order of chunk group(s) ${goodChunkGroups}`].filter(Boolean).join("\n");
+          })].join("\n")));
+        }
+        usedModules.add(/** @type {CssModule} */fallbackModule);
+      }
+    }
+    this._sortedModulesCache.set(chunk, usedModules);
+    return usedModules;
+  }
+
+  /**
+   * @private
+   * @param {Compiler} compiler compiler
+   * @param {Compilation} compilation compilation
+   * @param {Chunk} chunk chunk
+   * @param {CssModule[]} modules modules
+   * @param {Compiler["requestShortener"]} requestShortener request shortener
+   * @param {string} filenameTemplate filename template
+   * @param {Parameters<Exclude<Required<Configuration>['output']['filename'], string | undefined>>[0]} pathData path data
+   * @returns {Source} source
+   */
+  renderContentAsset(compiler, compilation, chunk, modules, requestShortener, filenameTemplate, pathData) {
+    const usedModules = this.sortModules(compilation, chunk, modules, requestShortener);
+    const {
+      ConcatSource,
+      SourceMapSource,
+      RawSource
+    } = compiler.webpack.sources;
+    const source = new ConcatSource();
+    const externalsSource = new ConcatSource();
+    for (const module of usedModules) {
+      let content = module.content.toString();
+      const readableIdentifier = module.readableIdentifier(requestShortener);
+      const startsWithAtRuleImport = content.startsWith("@import url");
+      let header;
+      if (compilation.outputOptions.pathinfo) {
+        // From https://github.com/webpack/webpack/blob/29eff8a74ecc2f87517b627dee451c2af9ed3f3f/lib/ModuleInfoHeaderPlugin.js#L191-L194
+        const reqStr = readableIdentifier.replace(/\*\//g, "*_/");
+        const reqStrStar = "*".repeat(reqStr.length);
+        const headerStr = `/*!****${reqStrStar}****!*\\\n  !*** ${reqStr} ***!\n  \\****${reqStrStar}****/\n`;
+        header = new RawSource(headerStr);
+      }
+      if (startsWithAtRuleImport) {
+        if (typeof header !== "undefined") {
+          externalsSource.add(header);
+        }
+
+        // HACK for IE
+        // http://stackoverflow.com/a/14676665/1458162
+        if (module.media || module.supports || typeof module.layer === "string") {
+          let atImportExtra = "";
+          const needLayer = typeof module.layer === "string";
+          if (needLayer) {
+            atImportExtra += module.layer.length > 0 ? ` layer(${module.layer})` : " layer";
+          }
+          if (module.supports) {
+            atImportExtra += ` supports(${module.supports})`;
+          }
+          if (module.media) {
+            atImportExtra += ` ${module.media}`;
+          }
+
+          // insert media into the @import
+          // this is rar
+          // TODO improve this and parse the CSS to support multiple medias
+          content = content.replace(/;|\s*$/, `${atImportExtra};`);
+        }
+        externalsSource.add(content);
+        externalsSource.add("\n");
+      } else {
+        if (typeof header !== "undefined") {
+          source.add(header);
+        }
+        if (module.supports) {
+          source.add(`@supports (${module.supports}) {\n`);
+        }
+        if (module.media) {
+          source.add(`@media ${module.media} {\n`);
+        }
+        const needLayer = typeof module.layer === "string";
+        if (needLayer) {
+          source.add(`@layer${module.layer.length > 0 ? ` ${module.layer}` : ""} {\n`);
+        }
+        const {
+          path: filename
+        } = compilation.getPathWithInfo(filenameTemplate, pathData);
+        const undoPath = getUndoPath(filename, compiler.outputPath, false);
+
+        // replacements
+        content = content.replace(new RegExp(ABSOLUTE_PUBLIC_PATH, "g"), "");
+        content = content.replace(new RegExp(SINGLE_DOT_PATH_SEGMENT, "g"), ".");
+        content = content.replace(new RegExp(AUTO_PUBLIC_PATH, "g"), undoPath);
+        const entryOptions = chunk.getEntryOptions();
+        const baseUriReplacement = entryOptions && entryOptions.baseUri || undoPath;
+        content = content.replace(new RegExp(BASE_URI, "g"), baseUriReplacement);
+        if (module.sourceMap) {
+          source.add(new SourceMapSource(content, readableIdentifier, module.sourceMap.toString()));
+        } else {
+          source.add(new RawSource(content));
+        }
+        source.add("\n");
+        if (needLayer) {
+          source.add("}\n");
+        }
+        if (module.media) {
+          source.add("}\n");
+        }
+        if (module.supports) {
+          source.add("}\n");
+        }
+      }
+    }
+    return new ConcatSource(externalsSource, source);
+  }
+}
+MiniCssExtractPlugin.pluginName = pluginName;
+MiniCssExtractPlugin.pluginSymbol = pluginSymbol;
+MiniCssExtractPlugin.loader = require.resolve("./loader");
+module.exports = MiniCssExtractPlugin;
Index: frontend/node_modules/mini-css-extract-plugin/dist/loader-options.json
===================================================================
--- frontend/node_modules/mini-css-extract-plugin/dist/loader-options.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/mini-css-extract-plugin/dist/loader-options.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,37 @@
+{
+  "title": "Mini CSS Extract Plugin Loader options",
+  "type": "object",
+  "additionalProperties": false,
+  "properties": {
+    "publicPath": {
+      "anyOf": [
+        {
+          "type": "string"
+        },
+        {
+          "instanceof": "Function"
+        }
+      ],
+      "description": "Specifies a custom public path for the external resources like images, files, etc inside CSS.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#publicpath"
+    },
+    "emit": {
+      "type": "boolean",
+      "description": "If true, emits a file (writes a file to the filesystem). If false, the plugin will extract the CSS but will not emit the file",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#emit"
+    },
+    "esModule": {
+      "type": "boolean",
+      "description": "Generates JS modules that use the ES modules syntax.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#esmodule"
+    },
+    "layer": {
+      "type": "string"
+    },
+    "defaultExport": {
+      "type": "boolean",
+      "description": "Duplicate the named export with CSS modules locals to the default export (only when `esModules: true` for css-loader).",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#defaultexports"
+    }
+  }
+}
Index: frontend/node_modules/mini-css-extract-plugin/dist/loader.js
===================================================================
--- frontend/node_modules/mini-css-extract-plugin/dist/loader.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/mini-css-extract-plugin/dist/loader.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,412 @@
+"use strict";
+
+const path = require("path");
+const schema = require("./loader-options.json");
+const {
+  ABSOLUTE_PUBLIC_PATH,
+  AUTO_PUBLIC_PATH,
+  BASE_URI,
+  SINGLE_DOT_PATH_SEGMENT,
+  evalModuleCode,
+  findModuleById,
+  stringifyLocal,
+  stringifyRequest
+} = require("./utils");
+const MiniCssExtractPlugin = require("./index");
+
+/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */
+/** @typedef {import("webpack").Compiler} Compiler */
+/** @typedef {import("webpack").Compilation} Compilation */
+/** @typedef {import("webpack").Chunk} Chunk */
+/** @typedef {import("webpack").Module} Module */
+/** @typedef {import("webpack").sources.Source} Source */
+/** @typedef {import("webpack").AssetInfo} AssetInfo */
+/** @typedef {import("webpack").NormalModule} NormalModule */
+/** @typedef {import("./index.js").LoaderOptions} LoaderOptions */
+
+// eslint-disable-next-line jsdoc/reject-function-type
+/** @typedef {{ [key: string]: string | Function }} Locals */
+
+// eslint-disable-next-line jsdoc/reject-any-type
+/** @typedef {any} EXPECTED_ANY */
+
+/**
+ * @typedef {object} Dependency
+ * @property {string} identifier identifier
+ * @property {string | null} context context
+ * @property {Buffer} content content
+ * @property {string=} media media
+ * @property {string=} supports supports
+ * @property {string=} layer layer
+ * @property {Buffer=} sourceMap source map
+ */
+
+/**
+ * @param {string} code code
+ * @param {{ loaderContext: import("webpack").LoaderContext<LoaderOptions>, options: LoaderOptions, locals: Locals | undefined }} context context
+ * @returns {string} code and HMR code
+ */
+function hotLoader(code, context) {
+  const localsJsonString = JSON.stringify(JSON.stringify(context.locals));
+  return `${code}
+    if(module.hot) {
+      (function() {
+        var localsJsonString = ${localsJsonString};
+        // ${Date.now()}
+        var cssReload = require(${stringifyRequest(context.loaderContext, path.join(__dirname, "hmr/hotModuleReplacement.js"))})(module.id, ${JSON.stringify(context.options)});
+        // only invalidate when locals change
+        if (
+          module.hot.data &&
+          module.hot.data.value &&
+          module.hot.data.value !== localsJsonString
+        ) {
+          module.hot.invalidate();
+        } else {
+          module.hot.accept();
+        }
+        module.hot.dispose(function(data) {
+          data.value = localsJsonString;
+          cssReload();
+        });
+      })();
+    }
+  `;
+}
+
+/**
+ * @this {import("webpack").LoaderContext<LoaderOptions>}
+ * @param {string} request request
+ */
+function pitch(request) {
+  if (this._compiler && this._compiler.options && this._compiler.options.experiments && this._compiler.options.experiments.css && this._module && (this._module.type === "css" || this._module.type === "css/auto" || this._module.type === "css/global" || this._module.type === "css/module")) {
+    this.emitWarning(new Error('You can\'t use `experiments.css` (`experiments.futureDefaults` enable built-in CSS support by default) and `mini-css-extract-plugin` together, please set `experiments.css` to `false` or set `{ type: "javascript/auto" }` for rules with `mini-css-extract-plugin` in your webpack config (now `mini-css-extract-plugin` does nothing).'));
+    return;
+  }
+  const options = this.getOptions(/** @type {Schema} */schema);
+  const emit = typeof options.emit !== "undefined" ? options.emit : true;
+  const callback = this.async();
+  const optionsFromPlugin =
+  // @ts-expect-error
+  this[MiniCssExtractPlugin.pluginSymbol];
+  if (!optionsFromPlugin) {
+    callback(new Error("You forgot to add 'mini-css-extract-plugin' plugin (i.e. `{ plugins: [new MiniCssExtractPlugin()] }`), please read https://github.com/webpack/mini-css-extract-plugin#getting-started"));
+    return;
+  }
+  const {
+    webpack
+  } = /** @type {Compiler} */this._compiler;
+
+  /**
+   * @param {EXPECTED_ANY} originalExports original exports
+   * @param {Compilation=} compilation compilation
+   * @param {{ [name: string]: Source }=} assets assets
+   * @param {Map<string, AssetInfo>=} assetsInfo assets info
+   * @returns {void}
+   */
+  const handleExports = (originalExports, compilation, assets, assetsInfo) => {
+    /** @type {Locals | undefined} */
+    let locals;
+    let namedExport;
+    const esModule = typeof options.esModule !== "undefined" ? options.esModule : true;
+
+    /**
+     * @param {Dependency[] | [null, object][]} dependencies dependencies
+     */
+    const addDependencies = dependencies => {
+      // eslint-disable-next-line no-eq-null, eqeqeq
+      if (!Array.isArray(dependencies) && dependencies != null) {
+        throw new Error(`Exported value was not extracted as an array: ${JSON.stringify(dependencies)}`);
+      }
+      const identifierCountMap = new Map();
+      let lastDep;
+      for (const dependency of dependencies) {
+        if (!(/** @type {Dependency} */dependency.identifier) || !emit) {
+          continue;
+        }
+        const count = identifierCountMap.get(/** @type {Dependency} */dependency.identifier) || 0;
+        const CssDependency = MiniCssExtractPlugin.getCssDependency(webpack);
+
+        /** @type {NormalModule} */
+        this._module.addDependency(lastDep = new CssDependency(/** @type {Dependency} */
+        dependency, /** @type {Dependency} */
+        dependency.context, count));
+        identifierCountMap.set(/** @type {Dependency} */
+        dependency.identifier, count + 1);
+      }
+      if (lastDep && assets) {
+        lastDep.assets = assets;
+        lastDep.assetsInfo = assetsInfo;
+      }
+    };
+    try {
+      const exports = originalExports.__esModule ? originalExports.default : originalExports;
+      namedExport = originalExports.__esModule && (!originalExports.default || !("locals" in originalExports.default));
+      if (namedExport) {
+        for (const key of Object.keys(originalExports)) {
+          if (key !== "default") {
+            if (!locals) {
+              locals = {};
+            }
+
+            /** @type {Locals} */
+            locals[key] = originalExports[key];
+          }
+        }
+      } else {
+        locals = exports && exports.locals;
+      }
+
+      /** @type {Dependency[] | [null, Record<string, string>][]} */
+      let dependencies;
+      if (!Array.isArray(exports)) {
+        dependencies = [[null, exports]];
+      } else {
+        dependencies = exports.map(([id, content, media, sourceMap, supports, layer]) => {
+          let identifier = id;
+          let context;
+          if (compilation) {
+            const module = /** @type {Module} */
+            findModuleById(compilation, id);
+            identifier = module.identifier();
+            ({
+              context
+            } = module);
+          } else {
+            // TODO check if this context is used somewhere
+            context = this.rootContext;
+          }
+          return {
+            identifier,
+            context,
+            content: Buffer.from(content),
+            media,
+            supports,
+            layer,
+            sourceMap: sourceMap ? Buffer.from(JSON.stringify(sourceMap)) : undefined
+          };
+        });
+      }
+      addDependencies(dependencies);
+    } catch (err) {
+      callback(/** @type {Error} */err);
+      return;
+    }
+    const result = function makeResult() {
+      const defaultExport = typeof options.defaultExport !== "undefined" ? options.defaultExport : false;
+      if (locals) {
+        if (namedExport) {
+          const identifiers = [...function* generateIdentifiers() {
+            let identifierId = 0;
+            for (const key of Object.keys(locals)) {
+              identifierId += 1;
+              yield [`_${identifierId.toString(16)}`, key];
+            }
+          }()];
+          const localsString = identifiers.map(([id, key]) => `\nvar ${id} = ${stringifyLocal(/** @type {Locals} */locals[key])};`).join("");
+          const exportsString = `export { ${identifiers.map(([id, key]) => `${id} as ${JSON.stringify(key)}`).join(", ")} }`;
+          return defaultExport ? `${localsString}\n${exportsString}\nexport default { ${identifiers.map(([id, key]) => `${JSON.stringify(key)}: ${id}`).join(", ")} }\n` : `${localsString}\n${exportsString}\n`;
+        }
+        return `\n${esModule ? "export default" : "module.exports = "} ${JSON.stringify(locals)};`;
+      } else if (esModule) {
+        return defaultExport ? "\nexport {};export default {};" : "\nexport {};";
+      }
+      return "";
+    }();
+    let resultSource = `// extracted by ${MiniCssExtractPlugin.pluginName}`;
+
+    // only attempt hotreloading if the css is actually used for something other than hash values
+    resultSource += this.hot && emit ? hotLoader(result, {
+      loaderContext: this,
+      options,
+      locals
+    }) : result;
+    callback(null, resultSource);
+  };
+  let {
+    publicPath
+  } = /** @type {Compilation} */
+  this._compilation.outputOptions;
+  if (typeof options.publicPath === "string") {
+    publicPath = options.publicPath;
+  } else if (typeof options.publicPath === "function") {
+    publicPath = options.publicPath(this.resourcePath, this.rootContext);
+  }
+  if (publicPath === "auto") {
+    publicPath = AUTO_PUBLIC_PATH;
+  }
+  if (typeof optionsFromPlugin.experimentalUseImportModule === "undefined" && typeof this.importModule === "function" || optionsFromPlugin.experimentalUseImportModule) {
+    if (!this.importModule) {
+      callback(new Error("You are using 'experimentalUseImportModule' but 'this.importModule' is not available in loader context. You need to have at least webpack 5.33.2."));
+      return;
+    }
+    let publicPathForExtract;
+    if (typeof publicPath === "string") {
+      const isAbsolutePublicPath = /^[a-zA-Z][a-zA-Z\d+\-.]*?:/.test(publicPath);
+      publicPathForExtract = isAbsolutePublicPath ? publicPath : `${ABSOLUTE_PUBLIC_PATH}${publicPath.replace(/\./g, SINGLE_DOT_PATH_SEGMENT)}`;
+    } else {
+      publicPathForExtract = publicPath;
+    }
+    this.importModule(`${this._module && this._module.matchResource ? this._module.matchResource : this.resourcePath}.webpack[javascript/auto]!=!!!${request}`, {
+      layer: options.layer,
+      publicPath: (/** @type {string} */publicPathForExtract),
+      baseUri: `${BASE_URI}/`
+    },
+    /**
+     * @param {Error | null | undefined} error error
+     * @param {object} exports exports
+     */
+    (error, exports) => {
+      if (error) {
+        callback(error);
+        return;
+      }
+      handleExports(exports);
+    });
+    return;
+  }
+  const loaders = this.loaders.slice(this.loaderIndex + 1);
+  this.addDependency(this.resourcePath);
+  const childFilename = "*";
+  const outputOptions = {
+    filename: childFilename,
+    publicPath
+  };
+  const childCompiler = /** @type {Compilation} */
+  this._compilation.createChildCompiler(`${MiniCssExtractPlugin.pluginName} ${request}`, outputOptions);
+
+  // The templates are compiled and executed by NodeJS - similar to server side rendering
+  // Unfortunately this causes issues as some loaders require an absolute URL to support ES Modules
+  // The following config enables relative URL support for the child compiler
+  childCompiler.options.module = {
+    ...childCompiler.options.module
+  };
+  childCompiler.options.module.parser = {
+    ...childCompiler.options.module.parser
+  };
+  childCompiler.options.module.parser.javascript = {
+    ...childCompiler.options.module.parser.javascript,
+    url: "relative"
+  };
+  const {
+    NodeTemplatePlugin
+  } = webpack.node;
+  const {
+    NodeTargetPlugin
+  } = webpack.node;
+  new NodeTemplatePlugin().apply(childCompiler);
+  new NodeTargetPlugin().apply(childCompiler);
+  const {
+    EntryOptionPlugin
+  } = webpack;
+  const {
+    library: {
+      EnableLibraryPlugin
+    }
+  } = webpack;
+  new EnableLibraryPlugin("commonjs2").apply(childCompiler);
+  EntryOptionPlugin.applyEntryOption(childCompiler, this.context, {
+    child: {
+      library: {
+        type: "commonjs2"
+      },
+      import: [`!!${request}`]
+    }
+  });
+  const {
+    LimitChunkCountPlugin
+  } = webpack.optimize;
+  new LimitChunkCountPlugin({
+    maxChunks: 1
+  }).apply(childCompiler);
+  const {
+    NormalModule
+  } = webpack;
+  childCompiler.hooks.thisCompilation.tap(`${MiniCssExtractPlugin.pluginName} loader`,
+  /**
+   * @param {Compilation} compilation compilation
+   */
+  compilation => {
+    const normalModuleHook = NormalModule.getCompilationHooks(compilation).loader;
+    normalModuleHook.tap(`${MiniCssExtractPlugin.pluginName} loader`, (loaderContext, module) => {
+      if (module.request === request) {
+        module.loaders = loaders.map(loader => ({
+          type: null,
+          loader: loader.path,
+          options: loader.options,
+          ident: loader.ident
+        }));
+      }
+    });
+  });
+
+  /** @type {string | Buffer} */
+  let source;
+  childCompiler.hooks.compilation.tap(MiniCssExtractPlugin.pluginName,
+  /**
+   * @param {Compilation} compilation compilation
+   */
+  compilation => {
+    compilation.hooks.processAssets.tap(MiniCssExtractPlugin.pluginName, () => {
+      source = compilation.assets[childFilename] && compilation.assets[childFilename].source();
+
+      // Remove all chunk assets
+      for (const chunk of compilation.chunks) {
+        for (const file of chunk.files) {
+          compilation.deleteAsset(file);
+        }
+      }
+    });
+  });
+  childCompiler.runAsChild((error, entries, compilation_) => {
+    if (error) {
+      callback(error);
+      return;
+    }
+    const compilation = /** @type {Compilation} */compilation_;
+    if (compilation.errors.length > 0) {
+      callback(compilation.errors[0]);
+      return;
+    }
+
+    /** @type {{ [name: string]: Source }} */
+    const assets = Object.create(null);
+    /** @type {Map<string, AssetInfo>} */
+    const assetsInfo = new Map();
+    for (const asset of compilation.getAssets()) {
+      assets[asset.name] = asset.source;
+      assetsInfo.set(asset.name, asset.info);
+    }
+    for (const dep of compilation.fileDependencies) {
+      this.addDependency(dep);
+    }
+    for (const dep of compilation.contextDependencies) {
+      this.addContextDependency(dep);
+    }
+    if (!source) {
+      callback(new Error("Didn't get a result from child compiler"));
+      return;
+    }
+    let originalExports;
+    try {
+      originalExports = evalModuleCode(this, source, request);
+    } catch (err) {
+      callback(/** @type {Error} */err);
+      return;
+    }
+    handleExports(originalExports, compilation, assets, assetsInfo);
+  });
+}
+
+/**
+ * @this {import("webpack").LoaderContext<LoaderOptions>}
+ * @param {string} content content
+ * @returns {string | undefined} the original content
+ */
+function loader(content) {
+  if (this._compiler && this._compiler.options && this._compiler.options.experiments && this._compiler.options.experiments.css && this._module && (this._module.type === "css" || this._module.type === "css/auto" || this._module.type === "css/global" || this._module.type === "css/module")) {
+    return content;
+  }
+}
+module.exports = loader;
+module.exports.hotLoader = hotLoader;
+module.exports.pitch = pitch;
Index: frontend/node_modules/mini-css-extract-plugin/dist/plugin-options.json
===================================================================
--- frontend/node_modules/mini-css-extract-plugin/dist/plugin-options.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/mini-css-extract-plugin/dist/plugin-options.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,79 @@
+{
+  "title": "Mini CSS Extract Plugin options",
+  "type": "object",
+  "additionalProperties": false,
+  "properties": {
+    "filename": {
+      "anyOf": [
+        {
+          "type": "string",
+          "absolutePath": false,
+          "minLength": 1
+        },
+        {
+          "instanceof": "Function"
+        }
+      ],
+      "description": "This option determines the name of each output CSS file.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#filename"
+    },
+    "chunkFilename": {
+      "anyOf": [
+        {
+          "type": "string",
+          "absolutePath": false,
+          "minLength": 1
+        },
+        {
+          "instanceof": "Function"
+        }
+      ],
+      "description": "This option determines the name of non-entry chunk files.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#chunkfilename"
+    },
+    "experimentalUseImportModule": {
+      "type": "boolean",
+      "description": "Enable the experimental importModule approach instead of using child compilers. This uses less memory and is faster.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#experimentaluseimportmodule"
+    },
+    "ignoreOrder": {
+      "type": "boolean",
+      "description": "Remove Order Warnings.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#ignoreorder"
+    },
+    "insert": {
+      "description": "Inserts the `link` tag at the given position for non-initial (async) (https://webpack.js.org/concepts/under-the-hood/#chunks) CSS chunks.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#insert",
+      "anyOf": [
+        {
+          "type": "string"
+        },
+        {
+          "instanceof": "Function"
+        }
+      ]
+    },
+    "attributes": {
+      "description": "Adds custom attributes to the `link` tag for non-initial (async) (https://webpack.js.org/concepts/under-the-hood/#chunks) CSS chunks.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#attributes",
+      "type": "object"
+    },
+    "linkType": {
+      "anyOf": [
+        {
+          "enum": ["text/css"]
+        },
+        {
+          "type": "boolean"
+        }
+      ],
+      "description": "This option allows loading asynchronous chunks with a custom link type",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#linktype"
+    },
+    "runtime": {
+      "type": "boolean",
+      "description": "Enabled/Disables runtime generation. CSS will be still extracted and can be used for a custom loading methods.",
+      "link": "https://github.com/webpack/mini-css-extract-plugin#noRuntime"
+    }
+  }
+}
Index: frontend/node_modules/mini-css-extract-plugin/dist/utils.js
===================================================================
--- frontend/node_modules/mini-css-extract-plugin/dist/utils.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/mini-css-extract-plugin/dist/utils.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,413 @@
+"use strict";
+
+const NativeModule = require("module");
+const path = require("path");
+
+/** @typedef {import("webpack").Compilation} Compilation */
+/** @typedef {import("webpack").Module} Module */
+
+// eslint-disable-next-line jsdoc/reject-any-type
+/** @typedef {import("webpack").LoaderContext<any>} LoaderContext */
+
+/**
+ * @returns {boolean} always returns true
+ */
+function trueFn() {
+  return true;
+}
+
+/**
+ * @param {Compilation} compilation compilation
+ * @param {string | number} id module id
+ * @returns {null | Module} the found module
+ */
+function findModuleById(compilation, id) {
+  const {
+    modules,
+    chunkGraph
+  } = compilation;
+  for (const module of modules) {
+    const moduleId = typeof chunkGraph !== "undefined" ? chunkGraph.getModuleId(module) : module.id;
+    if (moduleId === id) {
+      return module;
+    }
+  }
+  return null;
+}
+
+/* eslint-disable jsdoc/reject-any-type */
+/**
+ * @param {LoaderContext} loaderContext loader context
+ * @param {string | Buffer} code code
+ * @param {string} filename filename
+ * @returns {Record<string, any>} exports of a module
+ */
+function evalModuleCode(loaderContext, code, filename) {
+  // @ts-expect-error
+  const module = new NativeModule(filename, loaderContext);
+  // @ts-expect-error
+  module.paths = NativeModule._nodeModulePaths(loaderContext.context);
+  module.filename = filename;
+  // @ts-expect-error
+  module._compile(code, filename);
+  return module.exports;
+}
+/* eslint-enable jsdoc/reject-any-type */
+
+/**
+ * @param {string} a a
+ * @param {string} b b
+ * @returns {0 | 1 | -1} result of comparing
+ */
+function compareIds(a, b) {
+  if (typeof a !== typeof b) {
+    return typeof a < typeof b ? -1 : 1;
+  }
+  if (a < b) {
+    return -1;
+  }
+  if (a > b) {
+    return 1;
+  }
+  return 0;
+}
+
+/**
+ * @param {Module} a a
+ * @param {Module} b b
+ * @returns {0 | 1 | -1} result of comparing
+ */
+function compareModulesByIdentifier(a, b) {
+  return compareIds(a.identifier(), b.identifier());
+}
+const MODULE_TYPE = "css/mini-extract";
+const AUTO_PUBLIC_PATH = "__mini_css_extract_plugin_public_path_auto__";
+const ABSOLUTE_PUBLIC_PATH = "webpack:///mini-css-extract-plugin/";
+const BASE_URI = "webpack://";
+const SINGLE_DOT_PATH_SEGMENT = "__mini_css_extract_plugin_single_dot_path_segment__";
+
+/**
+ * @param {string} str path
+ * @returns {boolean} true when path is absolute, otherwise false
+ */
+function isAbsolutePath(str) {
+  return path.posix.isAbsolute(str) || path.win32.isAbsolute(str);
+}
+const RELATIVE_PATH_REGEXP = /^\.\.?[/\\]/;
+
+/**
+ * @param {string} str string
+ * @returns {boolean} true when path is relative, otherwise false
+ */
+function isRelativePath(str) {
+  return RELATIVE_PATH_REGEXP.test(str);
+}
+
+// TODO simplify for the next major release
+/**
+ * @param {LoaderContext} loaderContext the loader context
+ * @param {string} request a request
+ * @returns {string} a stringified request
+ */
+function stringifyRequest(loaderContext, request) {
+  if (typeof loaderContext.utils !== "undefined" && typeof loaderContext.utils.contextify === "function") {
+    return JSON.stringify(loaderContext.utils.contextify(loaderContext.context || loaderContext.rootContext, request));
+  }
+  const splitted = request.split("!");
+  const {
+    context
+  } = loaderContext;
+  return JSON.stringify(splitted.map(part => {
+    // First, separate singlePath from query, because the query might contain paths again
+    const splittedPart = part.match(/^(.*?)(\?.*)/);
+    const query = splittedPart ? splittedPart[2] : "";
+    let singlePath = splittedPart ? splittedPart[1] : part;
+    if (isAbsolutePath(singlePath) && context) {
+      singlePath = path.relative(context, singlePath);
+      if (isAbsolutePath(singlePath)) {
+        // If singlePath still matches an absolute path, singlePath was on a different drive than context.
+        // In this case, we leave the path platform-specific without replacing any separators.
+        // @see https://github.com/webpack/loader-utils/pull/14
+        return singlePath + query;
+      }
+      if (isRelativePath(singlePath) === false) {
+        // Ensure that the relative path starts at least with ./ otherwise it would be a request into the modules directory (like node_modules).
+        singlePath = `./${singlePath}`;
+      }
+    }
+    return singlePath.replace(/\\/g, "/") + query;
+  }).join("!"));
+}
+
+/**
+ * @param {string} filename filename
+ * @param {string} outputPath output path
+ * @param {boolean} enforceRelative true when need to enforce relative path, otherwise false
+ * @returns {string} undo path
+ */
+function getUndoPath(filename, outputPath, enforceRelative) {
+  let depth = -1;
+  let append = "";
+  outputPath = outputPath.replace(/[\\/]$/, "");
+  for (const part of filename.split(/[/\\]+/)) {
+    if (part === "..") {
+      if (depth > -1) {
+        depth--;
+      } else {
+        const i = outputPath.lastIndexOf("/");
+        const j = outputPath.lastIndexOf("\\");
+        const pos = i < 0 ? j : j < 0 ? i : Math.max(i, j);
+        if (pos < 0) {
+          return `${outputPath}/`;
+        }
+        append = `${outputPath.slice(pos + 1)}/${append}`;
+        outputPath = outputPath.slice(0, pos);
+      }
+    } else if (part !== ".") {
+      depth++;
+    }
+  }
+  return depth > 0 ? `${"../".repeat(depth)}${append}` : enforceRelative ? `./${append}` : append;
+}
+
+/* eslint-disable jsdoc/reject-function-type */
+/**
+ * @param {string | Function} value local
+ * @returns {string} stringified local
+ */
+function stringifyLocal(value) {
+  return typeof value === "function" ? value.toString() : JSON.stringify(value);
+}
+/* eslint-enable jsdoc/reject-function-type */
+
+/**
+ * @param {string} str string
+ * @returns {string} string
+ */
+const toSimpleString = str => {
+  // eslint-disable-next-line no-implicit-coercion
+  if (`${+str}` === str) {
+    return str;
+  }
+  return JSON.stringify(str);
+};
+
+/**
+ * @param {string} str string
+ * @returns {string} quoted meta
+ */
+const quoteMeta = str => str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
+
+/**
+ * @param {string[]} items items
+ * @returns {string} common prefix
+ */
+const getCommonPrefix = items => {
+  let [prefix] = items;
+  for (let i = 1; i < items.length; i++) {
+    const item = items[i];
+    for (let prefixIndex = 0; prefixIndex < prefix.length; prefixIndex++) {
+      if (item[prefixIndex] !== prefix[prefixIndex]) {
+        prefix = prefix.slice(0, prefixIndex);
+        break;
+      }
+    }
+  }
+  return prefix;
+};
+
+/**
+ * @param {string[]} items items
+ * @returns {string} common suffix
+ */
+const getCommonSuffix = items => {
+  let [suffix] = items;
+  for (let i = 1; i < items.length; i++) {
+    const item = items[i];
+    for (let itemIndex = item.length - 1, suffixIndex = suffix.length - 1; suffixIndex >= 0; itemIndex--, suffixIndex--) {
+      if (item[itemIndex] !== suffix[suffixIndex]) {
+        suffix = suffix.slice(suffixIndex + 1);
+        break;
+      }
+    }
+  }
+  return suffix;
+};
+
+/**
+ * @param {Set<string>} itemsSet items set
+ * @param {(str: string) => string | false} getKey get key function
+ * @param {(str: string[]) => boolean} condition condition
+ * @returns {string[][]} list of common items
+ */
+const popCommonItems = (itemsSet, getKey, condition) => {
+  /** @type {Map<string, string[]>} */
+  const map = new Map();
+  for (const item of itemsSet) {
+    const key = getKey(item);
+    if (key) {
+      let list = map.get(key);
+      if (list === undefined) {
+        /** @type {string[]} */
+        list = [];
+        map.set(key, list);
+      }
+      list.push(item);
+    }
+  }
+
+  /** @type {string[][]} */
+  const result = [];
+  for (const list of map.values()) {
+    if (condition(list)) {
+      for (const item of list) {
+        itemsSet.delete(item);
+      }
+      result.push(list);
+    }
+  }
+  return result;
+};
+
+/**
+ * @param {string[]} itemsArr array of items
+ * @returns {string} regexp
+ */
+const itemsToRegexp = itemsArr => {
+  if (itemsArr.length === 1) {
+    return quoteMeta(itemsArr[0]);
+  }
+
+  /** @type {string[]} */
+  const finishedItems = [];
+
+  // merge single char items: (a|b|c|d|ef) => ([abcd]|ef)
+  let countOfSingleCharItems = 0;
+  for (const item of itemsArr) {
+    if (item.length === 1) {
+      countOfSingleCharItems++;
+    }
+  }
+
+  // special case for only single char items
+  if (countOfSingleCharItems === itemsArr.length) {
+    return `[${quoteMeta(itemsArr.sort().join(""))}]`;
+  }
+  const items = new Set(itemsArr.sort());
+  if (countOfSingleCharItems > 2) {
+    let singleCharItems = "";
+    for (const item of items) {
+      if (item.length === 1) {
+        singleCharItems += item;
+        items.delete(item);
+      }
+    }
+    finishedItems.push(`[${quoteMeta(singleCharItems)}]`);
+  }
+
+  // special case for 2 items with common prefix/suffix
+  if (finishedItems.length === 0 && items.size === 2) {
+    const prefix = getCommonPrefix(itemsArr);
+    const suffix = getCommonSuffix(itemsArr.map(item => item.slice(prefix.length)));
+    if (prefix.length > 0 || suffix.length > 0) {
+      return `${quoteMeta(prefix)}${itemsToRegexp(itemsArr.map(i => i.slice(prefix.length, -suffix.length || undefined)))}${quoteMeta(suffix)}`;
+    }
+  }
+
+  // special case for 2 items with common suffix
+  if (finishedItems.length === 0 && items.size === 2) {
+    /** @type {Iterator<string>} */
+    const it = items[Symbol.iterator]();
+    const a = it.next().value;
+    const b = it.next().value;
+    if (a.length > 0 && b.length > 0 && a.slice(-1) === b.slice(-1)) {
+      return `${itemsToRegexp([a.slice(0, -1), b.slice(0, -1)])}${quoteMeta(a.slice(-1))}`;
+    }
+  }
+
+  // find common prefix: (a1|a2|a3|a4|b5) => (a(1|2|3|4)|b5)
+  const prefixed = popCommonItems(items, item => item.length >= 1 ? item[0] : false, list => {
+    if (list.length >= 3) return true;
+    if (list.length <= 1) return false;
+    return list[0][1] === list[1][1];
+  });
+  for (const prefixedItems of prefixed) {
+    const prefix = getCommonPrefix(prefixedItems);
+    finishedItems.push(`${quoteMeta(prefix)}${itemsToRegexp(prefixedItems.map(i => i.slice(prefix.length)))}`);
+  }
+
+  // find common suffix: (a1|b1|c1|d1|e2) => ((a|b|c|d)1|e2)
+  const suffixed = popCommonItems(items, item => item.length >= 1 ? item.slice(-1) : false, list => {
+    if (list.length >= 3) return true;
+    if (list.length <= 1) return false;
+    return list[0].slice(-2) === list[1].slice(-2);
+  });
+  for (const suffixedItems of suffixed) {
+    const suffix = getCommonSuffix(suffixedItems);
+    finishedItems.push(`${itemsToRegexp(suffixedItems.map(i => i.slice(0, -suffix.length)))}${quoteMeta(suffix)}`);
+  }
+
+  // TODO further optimize regexp, i. e.
+  // use ranges: (1|2|3|4|a) => [1-4a]
+  const conditional = [...finishedItems, ...Array.from(items, quoteMeta)];
+  if (conditional.length === 1) return conditional[0];
+  return `(${conditional.join("|")})`;
+};
+
+/**
+ * @param {string[]} positiveItems positive items
+ * @param {string[]} negativeItems negative items
+ * @returns {(val: string) => string} a template function to determine the value at runtime
+ */
+const compileBooleanMatcherFromLists = (positiveItems, negativeItems) => {
+  if (positiveItems.length === 0) {
+    return () => "false";
+  }
+  if (negativeItems.length === 0) {
+    return () => "true";
+  }
+  if (positiveItems.length === 1) {
+    return value => `${toSimpleString(positiveItems[0])} == ${value}`;
+  }
+  if (negativeItems.length === 1) {
+    return value => `${toSimpleString(negativeItems[0])} != ${value}`;
+  }
+  const positiveRegexp = itemsToRegexp(positiveItems);
+  const negativeRegexp = itemsToRegexp(negativeItems);
+  if (positiveRegexp.length <= negativeRegexp.length) {
+    return value => `/^${positiveRegexp}$/.test(${value})`;
+  }
+  return value => `!/^${negativeRegexp}$/.test(${value})`;
+};
+
+// TODO simplify in the next major release and use it from webpack
+/**
+ * @param {Record<string | number, boolean>} map value map
+ * @returns {boolean | ((value: string) => string)} true/false, when unconditionally true/false, or a template function to determine the value at runtime
+ */
+const compileBooleanMatcher = map => {
+  const positiveItems = Object.keys(map).filter(i => map[i]);
+  const negativeItems = Object.keys(map).filter(i => !map[i]);
+  if (positiveItems.length === 0) {
+    return false;
+  }
+  if (negativeItems.length === 0) {
+    return true;
+  }
+  return compileBooleanMatcherFromLists(positiveItems, negativeItems);
+};
+module.exports = {
+  ABSOLUTE_PUBLIC_PATH,
+  AUTO_PUBLIC_PATH,
+  BASE_URI,
+  MODULE_TYPE,
+  SINGLE_DOT_PATH_SEGMENT,
+  compareModulesByIdentifier,
+  compileBooleanMatcher,
+  evalModuleCode,
+  findModuleById,
+  getUndoPath,
+  stringifyLocal,
+  stringifyRequest,
+  trueFn
+};
