{
"version": 3,
"sources": ["../../../node_modules/@rails/ujs/app/assets/javascripts/rails-ujs.esm.js", "../../../node_modules/@thebespokepixel/es-tinycolor/index.mjs", "../../../node_modules/@upstream/cobot_assets/src/customize-colors.js", "../../javascript/application.js"],
"sourcesContent": ["/*\nUnobtrusive JavaScript\nhttps://github.com/rails/rails/blob/main/actionview/app/javascript\nReleased under the MIT license\n */\nconst linkClickSelector = \"a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]\";\n\nconst buttonClickSelector = {\n selector: \"button[data-remote]:not([form]), button[data-confirm]:not([form])\",\n exclude: \"form button\"\n};\n\nconst inputChangeSelector = \"select[data-remote], input[data-remote], textarea[data-remote]\";\n\nconst formSubmitSelector = \"form:not([data-turbo=true])\";\n\nconst formInputClickSelector = \"form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])\";\n\nconst formDisableSelector = \"input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled\";\n\nconst formEnableSelector = \"input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled\";\n\nconst fileInputSelector = \"input[name][type=file]:not([disabled])\";\n\nconst linkDisableSelector = \"a[data-disable-with], a[data-disable]\";\n\nconst buttonDisableSelector = \"button[data-remote][data-disable-with], button[data-remote][data-disable]\";\n\nlet nonce = null;\n\nconst loadCSPNonce = () => {\n const metaTag = document.querySelector(\"meta[name=csp-nonce]\");\n return nonce = metaTag && metaTag.content;\n};\n\nconst cspNonce = () => nonce || loadCSPNonce();\n\nconst m = Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector;\n\nconst matches = function(element, selector) {\n if (selector.exclude) {\n return m.call(element, selector.selector) && !m.call(element, selector.exclude);\n } else {\n return m.call(element, selector);\n }\n};\n\nconst EXPANDO = \"_ujsData\";\n\nconst getData = (element, key) => element[EXPANDO] ? element[EXPANDO][key] : undefined;\n\nconst setData = function(element, key, value) {\n if (!element[EXPANDO]) {\n element[EXPANDO] = {};\n }\n return element[EXPANDO][key] = value;\n};\n\nconst $ = selector => Array.prototype.slice.call(document.querySelectorAll(selector));\n\nconst isContentEditable = function(element) {\n var isEditable = false;\n do {\n if (element.isContentEditable) {\n isEditable = true;\n break;\n }\n element = element.parentElement;\n } while (element);\n return isEditable;\n};\n\nconst csrfToken = () => {\n const meta = document.querySelector(\"meta[name=csrf-token]\");\n return meta && meta.content;\n};\n\nconst csrfParam = () => {\n const meta = document.querySelector(\"meta[name=csrf-param]\");\n return meta && meta.content;\n};\n\nconst CSRFProtection = xhr => {\n const token = csrfToken();\n if (token) {\n return xhr.setRequestHeader(\"X-CSRF-Token\", token);\n }\n};\n\nconst refreshCSRFTokens = () => {\n const token = csrfToken();\n const param = csrfParam();\n if (token && param) {\n return $('form input[name=\"' + param + '\"]').forEach((input => input.value = token));\n }\n};\n\nconst AcceptHeaders = {\n \"*\": \"*/*\",\n text: \"text/plain\",\n html: \"text/html\",\n xml: \"application/xml, text/xml\",\n json: \"application/json, text/javascript\",\n script: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n};\n\nconst ajax = options => {\n options = prepareOptions(options);\n var xhr = createXHR(options, (function() {\n const response = processResponse(xhr.response != null ? xhr.response : xhr.responseText, xhr.getResponseHeader(\"Content-Type\"));\n if (Math.floor(xhr.status / 100) === 2) {\n if (typeof options.success === \"function\") {\n options.success(response, xhr.statusText, xhr);\n }\n } else {\n if (typeof options.error === \"function\") {\n options.error(response, xhr.statusText, xhr);\n }\n }\n return typeof options.complete === \"function\" ? options.complete(xhr, xhr.statusText) : undefined;\n }));\n if (options.beforeSend && !options.beforeSend(xhr, options)) {\n return false;\n }\n if (xhr.readyState === XMLHttpRequest.OPENED) {\n return xhr.send(options.data);\n }\n};\n\nvar prepareOptions = function(options) {\n options.url = options.url || location.href;\n options.type = options.type.toUpperCase();\n if (options.type === \"GET\" && options.data) {\n if (options.url.indexOf(\"?\") < 0) {\n options.url += \"?\" + options.data;\n } else {\n options.url += \"&\" + options.data;\n }\n }\n if (!(options.dataType in AcceptHeaders)) {\n options.dataType = \"*\";\n }\n options.accept = AcceptHeaders[options.dataType];\n if (options.dataType !== \"*\") {\n options.accept += \", */*; q=0.01\";\n }\n return options;\n};\n\nvar createXHR = function(options, done) {\n const xhr = new XMLHttpRequest;\n xhr.open(options.type, options.url, true);\n xhr.setRequestHeader(\"Accept\", options.accept);\n if (typeof options.data === \"string\") {\n xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded; charset=UTF-8\");\n }\n if (!options.crossDomain) {\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n CSRFProtection(xhr);\n }\n xhr.withCredentials = !!options.withCredentials;\n xhr.onreadystatechange = function() {\n if (xhr.readyState === XMLHttpRequest.DONE) {\n return done(xhr);\n }\n };\n return xhr;\n};\n\nvar processResponse = function(response, type) {\n if (typeof response === \"string\" && typeof type === \"string\") {\n if (type.match(/\\bjson\\b/)) {\n try {\n response = JSON.parse(response);\n } catch (error) {}\n } else if (type.match(/\\b(?:java|ecma)script\\b/)) {\n const script = document.createElement(\"script\");\n script.setAttribute(\"nonce\", cspNonce());\n script.text = response;\n document.head.appendChild(script).parentNode.removeChild(script);\n } else if (type.match(/\\b(xml|html|svg)\\b/)) {\n const parser = new DOMParser;\n type = type.replace(/;.+/, \"\");\n try {\n response = parser.parseFromString(response, type);\n } catch (error1) {}\n }\n }\n return response;\n};\n\nconst href = element => element.href;\n\nconst isCrossDomain = function(url) {\n const originAnchor = document.createElement(\"a\");\n originAnchor.href = location.href;\n const urlAnchor = document.createElement(\"a\");\n try {\n urlAnchor.href = url;\n return !((!urlAnchor.protocol || urlAnchor.protocol === \":\") && !urlAnchor.host || originAnchor.protocol + \"//\" + originAnchor.host === urlAnchor.protocol + \"//\" + urlAnchor.host);\n } catch (e) {\n return true;\n }\n};\n\nlet preventDefault;\n\nlet {CustomEvent: CustomEvent} = window;\n\nif (typeof CustomEvent !== \"function\") {\n CustomEvent = function(event, params) {\n const evt = document.createEvent(\"CustomEvent\");\n evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\n return evt;\n };\n CustomEvent.prototype = window.Event.prototype;\n ({preventDefault: preventDefault} = CustomEvent.prototype);\n CustomEvent.prototype.preventDefault = function() {\n const result = preventDefault.call(this);\n if (this.cancelable && !this.defaultPrevented) {\n Object.defineProperty(this, \"defaultPrevented\", {\n get() {\n return true;\n }\n });\n }\n return result;\n };\n}\n\nconst fire = (obj, name, data) => {\n const event = new CustomEvent(name, {\n bubbles: true,\n cancelable: true,\n detail: data\n });\n obj.dispatchEvent(event);\n return !event.defaultPrevented;\n};\n\nconst stopEverything = e => {\n fire(e.target, \"ujs:everythingStopped\");\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n};\n\nconst delegate = (element, selector, eventType, handler) => element.addEventListener(eventType, (function(e) {\n let {target: target} = e;\n while (!!(target instanceof Element) && !matches(target, selector)) {\n target = target.parentNode;\n }\n if (target instanceof Element && handler.call(target, e) === false) {\n e.preventDefault();\n e.stopPropagation();\n }\n}));\n\nconst toArray = e => Array.prototype.slice.call(e);\n\nconst serializeElement = (element, additionalParam) => {\n let inputs = [ element ];\n if (matches(element, \"form\")) {\n inputs = toArray(element.elements);\n }\n const params = [];\n inputs.forEach((function(input) {\n if (!input.name || input.disabled) {\n return;\n }\n if (matches(input, \"fieldset[disabled] *\")) {\n return;\n }\n if (matches(input, \"select\")) {\n toArray(input.options).forEach((function(option) {\n if (option.selected) {\n params.push({\n name: input.name,\n value: option.value\n });\n }\n }));\n } else if (input.checked || [ \"radio\", \"checkbox\", \"submit\" ].indexOf(input.type) === -1) {\n params.push({\n name: input.name,\n value: input.value\n });\n }\n }));\n if (additionalParam) {\n params.push(additionalParam);\n }\n return params.map((function(param) {\n if (param.name) {\n return `${encodeURIComponent(param.name)}=${encodeURIComponent(param.value)}`;\n } else {\n return param;\n }\n })).join(\"&\");\n};\n\nconst formElements = (form, selector) => {\n if (matches(form, \"form\")) {\n return toArray(form.elements).filter((el => matches(el, selector)));\n } else {\n return toArray(form.querySelectorAll(selector));\n }\n};\n\nconst handleConfirmWithRails = rails => function(e) {\n if (!allowAction(this, rails)) {\n stopEverything(e);\n }\n};\n\nconst confirm = (message, element) => window.confirm(message);\n\nvar allowAction = function(element, rails) {\n let callback;\n const message = element.getAttribute(\"data-confirm\");\n if (!message) {\n return true;\n }\n let answer = false;\n if (fire(element, \"confirm\")) {\n try {\n answer = rails.confirm(message, element);\n } catch (error) {}\n callback = fire(element, \"confirm:complete\", [ answer ]);\n }\n return answer && callback;\n};\n\nconst handleDisabledElement = function(e) {\n const element = this;\n if (element.disabled) {\n stopEverything(e);\n }\n};\n\nconst enableElement = e => {\n let element;\n if (e instanceof Event) {\n if (isXhrRedirect(e)) {\n return;\n }\n element = e.target;\n } else {\n element = e;\n }\n if (isContentEditable(element)) {\n return;\n }\n if (matches(element, linkDisableSelector)) {\n return enableLinkElement(element);\n } else if (matches(element, buttonDisableSelector) || matches(element, formEnableSelector)) {\n return enableFormElement(element);\n } else if (matches(element, formSubmitSelector)) {\n return enableFormElements(element);\n }\n};\n\nconst disableElement = e => {\n const element = e instanceof Event ? e.target : e;\n if (isContentEditable(element)) {\n return;\n }\n if (matches(element, linkDisableSelector)) {\n return disableLinkElement(element);\n } else if (matches(element, buttonDisableSelector) || matches(element, formDisableSelector)) {\n return disableFormElement(element);\n } else if (matches(element, formSubmitSelector)) {\n return disableFormElements(element);\n }\n};\n\nvar disableLinkElement = function(element) {\n if (getData(element, \"ujs:disabled\")) {\n return;\n }\n const replacement = element.getAttribute(\"data-disable-with\");\n if (replacement != null) {\n setData(element, \"ujs:enable-with\", element.innerHTML);\n element.innerHTML = replacement;\n }\n element.addEventListener(\"click\", stopEverything);\n return setData(element, \"ujs:disabled\", true);\n};\n\nvar enableLinkElement = function(element) {\n const originalText = getData(element, \"ujs:enable-with\");\n if (originalText != null) {\n element.innerHTML = originalText;\n setData(element, \"ujs:enable-with\", null);\n }\n element.removeEventListener(\"click\", stopEverything);\n return setData(element, \"ujs:disabled\", null);\n};\n\nvar disableFormElements = form => formElements(form, formDisableSelector).forEach(disableFormElement);\n\nvar disableFormElement = function(element) {\n if (getData(element, \"ujs:disabled\")) {\n return;\n }\n const replacement = element.getAttribute(\"data-disable-with\");\n if (replacement != null) {\n if (matches(element, \"button\")) {\n setData(element, \"ujs:enable-with\", element.innerHTML);\n element.innerHTML = replacement;\n } else {\n setData(element, \"ujs:enable-with\", element.value);\n element.value = replacement;\n }\n }\n element.disabled = true;\n return setData(element, \"ujs:disabled\", true);\n};\n\nvar enableFormElements = form => formElements(form, formEnableSelector).forEach((element => enableFormElement(element)));\n\nvar enableFormElement = function(element) {\n const originalText = getData(element, \"ujs:enable-with\");\n if (originalText != null) {\n if (matches(element, \"button\")) {\n element.innerHTML = originalText;\n } else {\n element.value = originalText;\n }\n setData(element, \"ujs:enable-with\", null);\n }\n element.disabled = false;\n return setData(element, \"ujs:disabled\", null);\n};\n\nvar isXhrRedirect = function(event) {\n const xhr = event.detail ? event.detail[0] : undefined;\n return xhr && xhr.getResponseHeader(\"X-Xhr-Redirect\");\n};\n\nconst handleMethodWithRails = rails => function(e) {\n const link = this;\n const method = link.getAttribute(\"data-method\");\n if (!method) {\n return;\n }\n if (isContentEditable(this)) {\n return;\n }\n const href = rails.href(link);\n const csrfToken$1 = csrfToken();\n const csrfParam$1 = csrfParam();\n const form = document.createElement(\"form\");\n let formContent = ``;\n if (csrfParam$1 && csrfToken$1 && !isCrossDomain(href)) {\n formContent += ``;\n }\n formContent += '';\n form.method = \"post\";\n form.action = href;\n form.target = link.target;\n form.innerHTML = formContent;\n form.style.display = \"none\";\n document.body.appendChild(form);\n form.querySelector('[type=\"submit\"]').click();\n stopEverything(e);\n};\n\nconst isRemote = function(element) {\n const value = element.getAttribute(\"data-remote\");\n return value != null && value !== \"false\";\n};\n\nconst handleRemoteWithRails = rails => function(e) {\n let data, method, url;\n const element = this;\n if (!isRemote(element)) {\n return true;\n }\n if (!fire(element, \"ajax:before\")) {\n fire(element, \"ajax:stopped\");\n return false;\n }\n if (isContentEditable(element)) {\n fire(element, \"ajax:stopped\");\n return false;\n }\n const withCredentials = element.getAttribute(\"data-with-credentials\");\n const dataType = element.getAttribute(\"data-type\") || \"script\";\n if (matches(element, formSubmitSelector)) {\n const button = getData(element, \"ujs:submit-button\");\n method = getData(element, \"ujs:submit-button-formmethod\") || element.getAttribute(\"method\") || \"get\";\n url = getData(element, \"ujs:submit-button-formaction\") || element.getAttribute(\"action\") || location.href;\n if (method.toUpperCase() === \"GET\") {\n url = url.replace(/\\?.*$/, \"\");\n }\n if (element.enctype === \"multipart/form-data\") {\n data = new FormData(element);\n if (button != null) {\n data.append(button.name, button.value);\n }\n } else {\n data = serializeElement(element, button);\n }\n setData(element, \"ujs:submit-button\", null);\n setData(element, \"ujs:submit-button-formmethod\", null);\n setData(element, \"ujs:submit-button-formaction\", null);\n } else if (matches(element, buttonClickSelector) || matches(element, inputChangeSelector)) {\n method = element.getAttribute(\"data-method\");\n url = element.getAttribute(\"data-url\");\n data = serializeElement(element, element.getAttribute(\"data-params\"));\n } else {\n method = element.getAttribute(\"data-method\");\n url = rails.href(element);\n data = element.getAttribute(\"data-params\");\n }\n ajax({\n type: method || \"GET\",\n url: url,\n data: data,\n dataType: dataType,\n beforeSend(xhr, options) {\n if (fire(element, \"ajax:beforeSend\", [ xhr, options ])) {\n return fire(element, \"ajax:send\", [ xhr ]);\n } else {\n fire(element, \"ajax:stopped\");\n return false;\n }\n },\n success(...args) {\n return fire(element, \"ajax:success\", args);\n },\n error(...args) {\n return fire(element, \"ajax:error\", args);\n },\n complete(...args) {\n return fire(element, \"ajax:complete\", args);\n },\n crossDomain: isCrossDomain(url),\n withCredentials: withCredentials != null && withCredentials !== \"false\"\n });\n stopEverything(e);\n};\n\nconst formSubmitButtonClick = function(e) {\n const button = this;\n const {form: form} = button;\n if (!form) {\n return;\n }\n if (button.name) {\n setData(form, \"ujs:submit-button\", {\n name: button.name,\n value: button.value\n });\n }\n setData(form, \"ujs:formnovalidate-button\", button.formNoValidate);\n setData(form, \"ujs:submit-button-formaction\", button.getAttribute(\"formaction\"));\n return setData(form, \"ujs:submit-button-formmethod\", button.getAttribute(\"formmethod\"));\n};\n\nconst preventInsignificantClick = function(e) {\n const link = this;\n const method = (link.getAttribute(\"data-method\") || \"GET\").toUpperCase();\n const data = link.getAttribute(\"data-params\");\n const metaClick = e.metaKey || e.ctrlKey;\n const insignificantMetaClick = metaClick && method === \"GET\" && !data;\n const nonPrimaryMouseClick = e.button != null && e.button !== 0;\n if (nonPrimaryMouseClick || insignificantMetaClick) {\n e.stopImmediatePropagation();\n }\n};\n\nconst Rails = {\n $: $,\n ajax: ajax,\n buttonClickSelector: buttonClickSelector,\n buttonDisableSelector: buttonDisableSelector,\n confirm: confirm,\n cspNonce: cspNonce,\n csrfToken: csrfToken,\n csrfParam: csrfParam,\n CSRFProtection: CSRFProtection,\n delegate: delegate,\n disableElement: disableElement,\n enableElement: enableElement,\n fileInputSelector: fileInputSelector,\n fire: fire,\n formElements: formElements,\n formEnableSelector: formEnableSelector,\n formDisableSelector: formDisableSelector,\n formInputClickSelector: formInputClickSelector,\n formSubmitButtonClick: formSubmitButtonClick,\n formSubmitSelector: formSubmitSelector,\n getData: getData,\n handleDisabledElement: handleDisabledElement,\n href: href,\n inputChangeSelector: inputChangeSelector,\n isCrossDomain: isCrossDomain,\n linkClickSelector: linkClickSelector,\n linkDisableSelector: linkDisableSelector,\n loadCSPNonce: loadCSPNonce,\n matches: matches,\n preventInsignificantClick: preventInsignificantClick,\n refreshCSRFTokens: refreshCSRFTokens,\n serializeElement: serializeElement,\n setData: setData,\n stopEverything: stopEverything\n};\n\nconst handleConfirm = handleConfirmWithRails(Rails);\n\nRails.handleConfirm = handleConfirm;\n\nconst handleMethod = handleMethodWithRails(Rails);\n\nRails.handleMethod = handleMethod;\n\nconst handleRemote = handleRemoteWithRails(Rails);\n\nRails.handleRemote = handleRemote;\n\nconst start = function() {\n if (window._rails_loaded) {\n throw new Error(\"rails-ujs has already been loaded!\");\n }\n window.addEventListener(\"pageshow\", (function() {\n $(formEnableSelector).forEach((function(el) {\n if (getData(el, \"ujs:disabled\")) {\n enableElement(el);\n }\n }));\n $(linkDisableSelector).forEach((function(el) {\n if (getData(el, \"ujs:disabled\")) {\n enableElement(el);\n }\n }));\n }));\n delegate(document, linkDisableSelector, \"ajax:complete\", enableElement);\n delegate(document, linkDisableSelector, \"ajax:stopped\", enableElement);\n delegate(document, buttonDisableSelector, \"ajax:complete\", enableElement);\n delegate(document, buttonDisableSelector, \"ajax:stopped\", enableElement);\n delegate(document, linkClickSelector, \"click\", preventInsignificantClick);\n delegate(document, linkClickSelector, \"click\", handleDisabledElement);\n delegate(document, linkClickSelector, \"click\", handleConfirm);\n delegate(document, linkClickSelector, \"click\", disableElement);\n delegate(document, linkClickSelector, \"click\", handleRemote);\n delegate(document, linkClickSelector, \"click\", handleMethod);\n delegate(document, buttonClickSelector, \"click\", preventInsignificantClick);\n delegate(document, buttonClickSelector, \"click\", handleDisabledElement);\n delegate(document, buttonClickSelector, \"click\", handleConfirm);\n delegate(document, buttonClickSelector, \"click\", disableElement);\n delegate(document, buttonClickSelector, \"click\", handleRemote);\n delegate(document, inputChangeSelector, \"change\", handleDisabledElement);\n delegate(document, inputChangeSelector, \"change\", handleConfirm);\n delegate(document, inputChangeSelector, \"change\", handleRemote);\n delegate(document, formSubmitSelector, \"submit\", handleDisabledElement);\n delegate(document, formSubmitSelector, \"submit\", handleConfirm);\n delegate(document, formSubmitSelector, \"submit\", handleRemote);\n delegate(document, formSubmitSelector, \"submit\", (e => setTimeout((() => disableElement(e)), 13)));\n delegate(document, formSubmitSelector, \"ajax:send\", disableElement);\n delegate(document, formSubmitSelector, \"ajax:complete\", enableElement);\n delegate(document, formInputClickSelector, \"click\", preventInsignificantClick);\n delegate(document, formInputClickSelector, \"click\", handleDisabledElement);\n delegate(document, formInputClickSelector, \"click\", handleConfirm);\n delegate(document, formInputClickSelector, \"click\", formSubmitButtonClick);\n document.addEventListener(\"DOMContentLoaded\", refreshCSRFTokens);\n document.addEventListener(\"DOMContentLoaded\", loadCSPNonce);\n return window._rails_loaded = true;\n};\n\nRails.start = start;\n\nif (typeof jQuery !== \"undefined\" && jQuery && jQuery.ajax) {\n if (jQuery.rails) {\n throw new Error(\"If you load both jquery_ujs and rails-ujs, use rails-ujs only.\");\n }\n jQuery.rails = Rails;\n jQuery.ajaxPrefilter((function(options, originalOptions, xhr) {\n if (!options.crossDomain) {\n return CSRFProtection(xhr);\n }\n }));\n}\n\nexport { Rails as default };\n", "const mathRound = Math.round;\nconst mathMin = Math.min;\nconst mathMax = Math.max;\nconst isOnePointZero = n => typeof n === 'string' && n.indexOf('.') !== -1 && parseFloat(n) === 1;\nconst isPercentage = n => typeof n === 'string' && n.indexOf('%') !== -1;\nconst roundIf01 = n => n < 1 ? mathRound(n) : n;\nconst roundAlpha = a => mathRound(100 * a) / 100;\nconst boundAlpha = a => {\n a = parseFloat(a);\n return isNaN(a) || a < 0 || a > 1 ? 1 : a;\n};\nconst hasAlpha = rgba => rgba.a < 1 && rgba.a >= 0;\nconst clamp01 = val => mathMin(1, mathMax(0, val));\nconst pad2 = c => c.length === 1 ? `0${c}` : `${c}`;\nconst CSS_INTEGER = '[-\\\\+]?\\\\d+%?';\nconst CSS_NUMBER = '[-\\\\+]?\\\\d*\\\\.\\\\d+%?';\nconst CSS_UNIT = `(?:${CSS_NUMBER})|(?:${CSS_INTEGER})`;\nconst isValidCSSUnit = color => new RegExp(CSS_UNIT).test(color);\nconst isValidCSSUnitRGB = rgb => isValidCSSUnit(rgb.r) && isValidCSSUnit(rgb.g) && isValidCSSUnit(rgb.b);\nconst PERMISSIVE_MATCH3 = `[\\\\s|\\\\(]+(${CSS_UNIT})[,|\\\\s]+(${CSS_UNIT})[,|\\\\s]+(${CSS_UNIT})\\\\s*\\\\)?`;\nconst PERMISSIVE_MATCH4 = `[\\\\s|\\\\(]+(${CSS_UNIT})[,|\\\\s]+(${CSS_UNIT})[,|\\\\s]+(${CSS_UNIT})[,|\\\\s]+(${CSS_UNIT})\\\\s*\\\\)?`;\nfunction bound01(n, max) {\n if (isOnePointZero(n)) {\n n = '100%';\n }\n\n const processPercent = isPercentage(n);\n n = mathMin(max, mathMax(0, parseFloat(n)));\n\n if (processPercent) {\n n = parseInt(n * max, 10) / 100;\n }\n\n if (Math.abs(n - max) < 0.000001) {\n return 1;\n }\n\n return n % max / parseFloat(max);\n}\n\nfunction _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nfunction ownKeys(object, enumerableOnly) {\n var keys = Object.keys(object);\n\n if (Object.getOwnPropertySymbols) {\n var symbols = Object.getOwnPropertySymbols(object);\n if (enumerableOnly) symbols = symbols.filter(function (sym) {\n return Object.getOwnPropertyDescriptor(object, sym).enumerable;\n });\n keys.push.apply(keys, symbols);\n }\n\n return keys;\n}\n\nfunction _objectSpread2(target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i] != null ? arguments[i] : {};\n\n if (i % 2) {\n ownKeys(source, true).forEach(function (key) {\n _defineProperty(target, key, source[key]);\n });\n } else if (Object.getOwnPropertyDescriptors) {\n Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));\n } else {\n ownKeys(source).forEach(function (key) {\n Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));\n });\n }\n }\n\n return target;\n}\n\nconst convertHexToInt = val => parseInt(val, 16);\nconst convertHexToDecimal = h => convertHexToInt(h) / 255;\nconst convertToPercentage = n => n <= 1 ? `${n * 100}%` : n;\nconst rawToRgba = raw => {\n const [r, g, b] = [raw._r, raw._g, raw._b].map(mathRound);\n return {\n r,\n g,\n b,\n a: raw._roundA\n };\n};\nconst rawToDeepRgba = raw => ({\n r: raw._r,\n g: raw._g,\n b: raw._b,\n a: raw._a\n});\nconst conformRgba = rgba => {\n const [r, g, b] = [rgba.r, rgba.g, rgba.b].map(n => bound01(n, 255) * 255);\n return {\n r,\n g,\n b,\n a: boundAlpha(rgba.a)\n };\n};\nconst rgbaToPercentageRgba = rgba => {\n const [r, g, b] = [rgba.r, rgba.g, rgba.b].map(n => `${mathRound(bound01(n, 255) * 100)}%`);\n return {\n r,\n g,\n b,\n a: rgba.a\n };\n};\nconst rgbaToString = rgba => rgba.a === 1 ? `rgb(${rgba.r}, ${rgba.g}, ${rgba.b})` : `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`;\nconst rgbaToArray = rgba => rgba.a === 1 ? [rgba.r, rgba.g, rgba.b] : [rgba.r, rgba.g, rgba.b, mathRound(rgba.a * 255)];\nconst rgbaToHex = (rgba, allowShort) => {\n const hex = rgbaToArray(rgba).map(n => n.toString(16)).map(pad2);\n return allowShort && hex.every(h => h.charAt(0) === h.charAt(1)) ? hex.map(h => h.charAt(0)).join('') : hex.join('');\n};\nconst rgbToHex = (rgba, allowShort) => rgbaToHex(_objectSpread2({}, rgba, {\n a: 1\n}), allowShort);\n\nconst calcBrightness = rgb => (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;\nfunction calcLuminance(rgb, deepRgb) {\n let R;\n let G;\n let B;\n const RsRGB = deepRgb.r / 255;\n const GsRGB = deepRgb.g / 255;\n const BsRGB = deepRgb.b / 255;\n\n if (RsRGB <= 0.03928) {\n R = RsRGB / 12.92;\n } else {\n R = ((RsRGB + 0.055) / 1.055) ** 2.4;\n }\n\n if (GsRGB <= 0.03928) {\n G = GsRGB / 12.92;\n } else {\n G = ((GsRGB + 0.055) / 1.055) ** 2.4;\n }\n\n if (BsRGB <= 0.03928) {\n B = BsRGB / 12.92;\n } else {\n B = ((BsRGB + 0.055) / 1.055) ** 2.4;\n }\n\n return 0.2126 * R + 0.7152 * G + 0.0722 * B;\n}\nfunction calcMix(color1, color2, amount) {\n amount = amount === 0 ? 0 : amount || 50;\n const rgb1 = new TinyColor(color1).toRgb();\n const rgb2 = new TinyColor(color2).toRgb();\n const p = amount / 100;\n const rgba = {\n r: (rgb2.r - rgb1.r) * p + rgb1.r,\n g: (rgb2.g - rgb1.g) * p + rgb1.g,\n b: (rgb2.b - rgb1.b) * p + rgb1.b,\n a: (rgb2.a - rgb1.a) * p + rgb1.a\n };\n return new TinyColor(rgba);\n}\n\nfunction validateWCAG2Parms(parms) {\n let level;\n let size;\n parms = parms || {\n level: 'AA',\n size: 'small'\n };\n level = (parms.level || 'AA').toUpperCase();\n size = (parms.size || 'small').toLowerCase();\n\n if (level !== 'AA' && level !== 'AAA') {\n level = 'AA';\n }\n\n if (size !== 'small' && size !== 'large') {\n size = 'small';\n }\n\n return {\n level,\n size\n };\n}\n\nfunction readability(color1, color2) {\n const c1 = new TinyColor(color1);\n const c2 = new TinyColor(color2);\n return (Math.max(c1.getLuminance(), c2.getLuminance()) + 0.05) / (Math.min(c1.getLuminance(), c2.getLuminance()) + 0.05);\n}\nfunction isReadable(color1, color2, wcag2) {\n const readable = readability(color1, color2);\n const wcag2Parms = validateWCAG2Parms(wcag2);\n let out = false;\n\n switch (wcag2Parms.level + wcag2Parms.size) {\n case 'AAlarge':\n out = readable >= 3;\n break;\n\n case 'AAAsmall':\n out = readable >= 7;\n break;\n\n default:\n out = readable >= 4.5;\n }\n\n return out;\n}\nfunction mostReadable(baseColor, colorList, args = {}) {\n const {\n includeFallbackColors,\n level,\n size\n } = args;\n let readable;\n let bestColor = null;\n let bestScore = 0;\n colorList.forEach(color => {\n readable = readability(baseColor, color);\n\n if (readable > bestScore) {\n bestScore = readable;\n bestColor = new TinyColor(color);\n }\n });\n\n if (isReadable(baseColor, bestColor, {\n level,\n size\n }) || !includeFallbackColors) {\n return bestColor;\n }\n\n args.includeFallbackColors = false;\n return mostReadable(baseColor, ['#fff', '#000'], args);\n}\n\nfunction combine(action, args) {\n const actions = {\n monochromatic,\n analogous,\n complement,\n splitcomplement,\n triad,\n tetrad\n };\n return actions[action](...args);\n}\nfunction complement(color) {\n const hsl = new TinyColor(color).toHsl();\n hsl.h = (hsl.h + 180) % 360;\n return new TinyColor(hsl);\n}\nfunction triad(color) {\n const hsl = new TinyColor(color).toHsl();\n const {\n h\n } = hsl;\n return [new TinyColor(color), new TinyColor({\n h: (h + 120) % 360,\n s: hsl.s,\n l: hsl.l\n }), new TinyColor({\n h: (h + 240) % 360,\n s: hsl.s,\n l: hsl.l\n })];\n}\nfunction tetrad(color) {\n const hsl = new TinyColor(color).toHsl();\n const {\n h\n } = hsl;\n return [new TinyColor(color), new TinyColor({\n h: (h + 90) % 360,\n s: hsl.s,\n l: hsl.l\n }), new TinyColor({\n h: (h + 180) % 360,\n s: hsl.s,\n l: hsl.l\n }), new TinyColor({\n h: (h + 270) % 360,\n s: hsl.s,\n l: hsl.l\n })];\n}\nfunction splitcomplement(color) {\n const hsl = new TinyColor(color).toHsl();\n const {\n h\n } = hsl;\n return [new TinyColor(color), new TinyColor({\n h: (h + 72) % 360,\n s: hsl.s,\n l: hsl.l\n }), new TinyColor({\n h: (h + 216) % 360,\n s: hsl.s,\n l: hsl.l\n })];\n}\nfunction analogous(color, results, slices) {\n results = results || 6;\n slices = slices || 30;\n const hsl = new TinyColor(color).toHsl();\n const part = 360 / slices;\n const ret = [new TinyColor(color)];\n\n for (hsl.h = (hsl.h - (part * results >> 1) + 720) % 360; --results;) {\n hsl.h = (hsl.h + part) % 360;\n ret.push(new TinyColor(hsl));\n }\n\n return ret;\n}\nfunction monochromatic(color, results) {\n results = results || 6;\n const hsv = new TinyColor(color).toHsv();\n let {\n h,\n s,\n v\n } = hsv;\n const ret = [];\n const modification = 1 / results;\n\n while (results--) {\n ret.push(new TinyColor({\n h,\n s,\n v\n }));\n v = (v + modification) % 1;\n }\n\n return ret;\n}\n\nfunction modify(action, args) {\n const actions = {\n desaturate,\n saturate,\n greyscale,\n lighten,\n brighten,\n darken,\n spin\n };\n const color = actions[action](...args);\n const [source] = args;\n source._r = color._r;\n source._g = color._g;\n source._b = color._b;\n source.setAlpha(color._a);\n return source;\n}\nfunction desaturate(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n const hsl = new TinyColor(color).toHsl();\n hsl.s -= amount / 100;\n hsl.s = clamp01(hsl.s);\n return new TinyColor(hsl);\n}\nfunction saturate(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n const hsl = new TinyColor(color).toHsl();\n hsl.s += amount / 100;\n hsl.s = clamp01(hsl.s);\n return new TinyColor(hsl);\n}\nfunction greyscale(color) {\n return new TinyColor(color).desaturate(100);\n}\nfunction lighten(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n const hsl = new TinyColor(color).toHsl();\n hsl.l += amount / 100;\n hsl.l = clamp01(hsl.l);\n return new TinyColor(hsl);\n}\nfunction brighten(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n const rgb = new TinyColor(color).toRgb();\n rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * -(amount / 100))));\n rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * -(amount / 100))));\n rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * -(amount / 100))));\n return new TinyColor(rgb);\n}\nfunction darken(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n const hsl = new TinyColor(color).toHsl();\n hsl.l -= amount / 100;\n hsl.l = clamp01(hsl.l);\n return new TinyColor(hsl);\n}\nfunction spin(color, amount) {\n const hsl = new TinyColor(color).toHsl();\n const hue = (hsl.h + amount) % 360;\n hsl.h = hue < 0 ? 360 + hue : hue;\n return new TinyColor(hsl);\n}\n\nclass TinyColorExtension {\n constructor(api, id, opts = {}) {\n this.api = api;\n this.id = id;\n this.opts = opts;\n }\n\n use(specified) {\n this.wanted = specified;\n return this;\n }\n\n parse(input) {\n const result = this.api.find(input);\n return {\n as: format => Object.assign(result, {\n format\n }),\n rgba: {\n r: result.r,\n g: result.g,\n b: result.b,\n a: result.a\n },\n valueOf: () => result\n };\n }\n\n print(id, rgba) {\n return this.api.print(rgba, id);\n }\n\n complete(rgba) {\n const output = this.toString(rgba);\n delete this.wanted;\n return output;\n }\n\n}\n\nconst _template = {\n format: false,\n ok: false,\n r: 0,\n g: 0,\n b: 0,\n a: 1\n};\nclass TinyColorExtensionAPI {\n constructor() {\n this.colorspaces = {};\n this.opts = {\n alphaFormat: 'rgb',\n shortHex: false,\n upperCaseHex: false\n };\n }\n\n set(opts) {\n Object.assign(this.opts, opts);\n\n for (const id in this.colorspaces) {\n if ({}.hasOwnProperty.call(this.colorspaces, id)) {\n Object.assign(this.colorspaces[id].opts, opts);\n }\n }\n }\n\n add(id, opts) {\n this.colorspaces[id] = new TinyColorExtension(this, id, _objectSpread2({}, this.opts, {}, opts));\n\n if (opts.alias) {\n opts.alias.forEach(id_ => {\n this.colorspaces[id_] = this.colorspaces[id];\n });\n }\n\n return this.colorspaces[id];\n }\n\n find(input) {\n const color = _objectSpread2({}, _template);\n\n input = typeof input === 'string' ? input.trim().toLowerCase() : input;\n\n if (input) {\n for (const id in this.colorspaces) {\n if (this.colorspaces[id].shouldHandleInput(input)) {\n Object.assign(color, this.colorspaces[id].toRgb(input));\n color.format = color.format || id;\n color.ok = true;\n break;\n }\n }\n }\n\n return color;\n }\n\n raw(rgba, format) {\n if (format in this.colorspaces) {\n return this.colorspaces[format].toRaw(rgba);\n }\n\n return {\n r: rgba.r / 255,\n g: rgba.g / 255,\n b: rgba.b / 255,\n a: rgba.a\n };\n }\n\n print(rgba, original, format) {\n const specified = format;\n format = format || original;\n\n if (format in this.colorspaces) {\n return this.colorspaces[format].use(specified).complete(rgba);\n }\n\n return `[${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a * 255}]`;\n }\n\n}\n\nlet tinyCounter = 0;\nconst extensionApi = new TinyColorExtensionAPI();\nclass TinyColor {\n constructor(color, opts = {}) {\n color = color || '';\n\n if (color instanceof TinyColor) {\n return color;\n }\n\n const rgba = extensionApi.find(color);\n this._originalInput = color;\n this._r = roundIf01(rgba.r);\n this._g = roundIf01(rgba.g);\n this._b = roundIf01(rgba.b);\n this._a = rgba.a;\n this._roundA = roundAlpha(this._a);\n this._format = opts.format || rgba.format;\n this._gradientType = opts.gradientType;\n this._ok = rgba.ok;\n this._tc_id = TinyColor.newId();\n extensionApi.set(opts);\n }\n\n static newId() {\n return tinyCounter++;\n }\n\n static registerFormat(id, opts = {}) {\n return extensionApi.add(id, opts);\n }\n\n static equals(color1, color2) {\n if (!color1 || !color2) {\n return false;\n }\n\n return new TinyColor(color1).toRgbString() === new TinyColor(color2).toRgbString();\n }\n\n static fromRatio(color, opts) {\n if (typeof color === 'object') {\n const newColor = {};\n\n for (const i in color) {\n if ({}.hasOwnProperty.call(color, i)) {\n if (i === 'a') {\n newColor[i] = color[i];\n } else {\n newColor[i] = convertToPercentage(color[i]);\n }\n }\n }\n\n color = newColor;\n }\n\n return new TinyColor(color, opts);\n }\n\n static readability(color1, color2) {\n return readability(color1, color2);\n }\n\n static isReadable(color1, color2, wcag2) {\n return isReadable(color1, color2, wcag2);\n }\n\n static mostReadable(baseColor, colorList, args) {\n return mostReadable(baseColor, colorList, args);\n }\n\n static mix(color1, color2, amount) {\n return calcMix(color1, color2, amount);\n }\n\n isDark() {\n return this.getBrightness() < 128;\n }\n\n isLight() {\n return !this.isDark();\n }\n\n isValid() {\n return this._ok;\n }\n\n getOriginalInput() {\n return this._originalInput;\n }\n\n getFormat() {\n return this._format;\n }\n\n getAlpha() {\n return this._a;\n }\n\n getBrightness() {\n return calcBrightness(this.toRgb());\n }\n\n getLuminance() {\n return calcLuminance(this.toRgb(), rawToDeepRgba(this));\n }\n\n toString(format) {\n return extensionApi.print(rawToRgba(this), this._format, format);\n }\n\n toName() {\n return extensionApi.print(rawToRgba(this), 'name', 'toName');\n }\n\n toRgb() {\n return rawToDeepRgba(this);\n }\n\n toRgbString() {\n return rgbaToString(rawToRgba(this));\n }\n\n toRgbArray() {\n return rgbaToArray(rawToRgba(this));\n }\n\n toPercentageRgb() {\n return rgbaToPercentageRgba(rawToDeepRgba(this));\n }\n\n toPercentageRgbString() {\n return rgbaToString(rgbaToPercentageRgba(rawToRgba(this)));\n }\n\n toHex(allow3Char) {\n return rgbToHex(rawToRgba(this), allow3Char);\n }\n\n toHexString(allow3Char) {\n return `#${this.toHex(allow3Char)}`;\n }\n\n toHex8(allow4Char) {\n return rgbaToHex(rawToRgba(this), allow4Char);\n }\n\n toHex8String(allow4Char) {\n return `#${this.toHex8(allow4Char)}`;\n }\n\n toHsv() {\n return extensionApi.raw(rawToDeepRgba(this), 'hsv');\n }\n\n toHsvString() {\n return extensionApi.print(rawToDeepRgba(this), this._format, 'hsv');\n }\n\n toHsl() {\n return extensionApi.raw(rawToDeepRgba(this), 'hsl');\n }\n\n toHslString() {\n return extensionApi.print(rawToDeepRgba(this), this._format, 'hsl');\n }\n\n setAlpha(value) {\n this._a = boundAlpha(value);\n this._roundA = mathRound(100 * this._a) / 100;\n return this;\n }\n\n clone() {\n return new TinyColor(this.toString());\n }\n\n lighten(...args) {\n return modify('lighten', [this, ...args]);\n }\n\n brighten(...args) {\n return modify('brighten', [this, ...args]);\n }\n\n darken(...args) {\n return modify('darken', [this, ...args]);\n }\n\n desaturate(...args) {\n return modify('desaturate', [this, ...args]);\n }\n\n saturate(...args) {\n return modify('saturate', [this, ...args]);\n }\n\n greyscale(...args) {\n return modify('greyscale', [this, ...args]);\n }\n\n spin(...args) {\n return modify('spin', [this, ...args]);\n }\n\n analogous(...args) {\n return combine('analogous', [this, ...args]);\n }\n\n complement(...args) {\n return combine('complement', [this, ...args]);\n }\n\n monochromatic(...args) {\n return combine('monochromatic', [this, ...args]);\n }\n\n splitcomplement(...args) {\n return combine('splitcomplement', [this, ...args]);\n }\n\n triad(...args) {\n return combine('triad', [this, ...args]);\n }\n\n tetrad(...args) {\n return combine('tetrad', [this, ...args]);\n }\n\n}\n\nconst matchers = function () {\n return {\n rgb: new RegExp(`rgb${PERMISSIVE_MATCH3}`),\n rgba: new RegExp(`rgba${PERMISSIVE_MATCH4}`)\n };\n}();\n\nfunction rgbStringToObject(color) {\n let r, g, b, a, match;\n\n if (match = matchers.rgb.exec(color)) {\n [r, g, b] = match.splice(1, 3);\n return {\n r,\n g,\n b\n };\n }\n\n if (match = matchers.rgba.exec(color)) {\n [r, g, b, a] = match.splice(1, 4);\n return {\n r,\n g,\n b,\n a\n };\n }\n\n return false;\n}\n\nconst api = TinyColor.registerFormat('rgb');\n\napi.shouldHandleInput = input => typeof input === 'object' && isValidCSSUnitRGB(input) && !isPercentage(input.r) || rgbStringToObject(input);\n\napi.toRgb = input => typeof input === 'object' && conformRgba(input) || conformRgba(rgbStringToObject(input));\n\napi.toRaw = rgba => rgba;\n\napi.toString = rgba => rgbaToString(rgba);\n\nconst api$1 = TinyColor.registerFormat('prgb');\n\napi$1.shouldHandleInput = input => {\n if (typeof input === 'string') {\n const rgbCheck = rgbStringToObject(input);\n return rgbCheck && isPercentage(rgbCheck.r);\n }\n\n return isValidCSSUnitRGB(input) && isPercentage(input.r);\n};\n\napi$1.toRgb = input => typeof input === 'object' ? conformRgba(input) : conformRgba(rgbStringToObject(input));\n\napi$1.toRaw = rgba => rgbaToPercentageRgba(rgba);\n\napi$1.toString = rgba => rgbaToString(rgbaToPercentageRgba(rgba));\n\nconst api$2 = TinyColor.registerFormat('hex', {\n alias: ['hex3', 'hex6']\n});\n\nconst matchers$1 = function () {\n return {\n hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n };\n}();\n\nfunction hexToRgba(color) {\n let match;\n\n if (match = matchers$1.hex3.exec(color)) {\n const [r, g, b] = match.splice(1, 3).map(h => `${h}${h}`).map(convertHexToInt);\n return {\n r,\n g,\n b,\n a: 1\n };\n }\n\n if (match = matchers$1.hex6.exec(color)) {\n const [r, g, b] = match.splice(1, 3).map(convertHexToInt);\n return {\n r,\n g,\n b,\n a: 1\n };\n }\n\n return false;\n}\n\nconst hexToString = (rgba, short = api$2.opts.shortHex) => `#${api$2.opts.upperCaseHex ? rgbToHex(rgba, short).toUpperCase() : rgbToHex(rgba, short)}`;\n\napi$2.shouldHandleInput = input => matchers$1.hex6.test(input) || matchers$1.hex3.test(input);\n\napi$2.toRgb = input => hexToRgba(input);\n\napi$2.toRaw = rgba => rgba;\n\napi$2.toString = rgba => {\n if (/^hex6?$/.test(api$2.wanted)) {\n return hexToString(rgba);\n }\n\n if (api$2.wanted === 'hex3') {\n return hexToString(rgba, true);\n }\n\n if (hasAlpha(rgba)) {\n return api$2.opts.alphaFormat === 'hex' ? hexToString(rgba) : api$2.print(api$2.opts.alphaFormat, rgba);\n }\n\n return hexToString(rgba);\n};\n\nconst api$3 = TinyColor.registerFormat('hex8', {\n alias: ['hex4']\n});\n\nconst matchers$2 = function () {\n return {\n hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n };\n}();\n\nfunction hexToRgba$1(color) {\n let match;\n\n if (match = matchers$2.hex4.exec(color)) {\n const a = convertHexToDecimal(`${match[4]}${match[4]}`);\n const [r, g, b] = match.splice(1, 3).map(h => `${h}${h}`).map(convertHexToInt);\n return {\n r,\n g,\n b,\n a\n };\n }\n\n if (match = matchers$2.hex8.exec(color)) {\n const a = convertHexToDecimal(match[4]);\n const [r, g, b] = match.splice(1, 3).map(convertHexToInt);\n return {\n r,\n g,\n b,\n a\n };\n }\n\n return false;\n}\n\nconst hexToString$1 = (rgba, short = api$3.opts.shortHex) => `#${api$3.opts.upperCaseHex ? rgbaToHex(rgba, short).toUpperCase() : rgbaToHex(rgba, short)}`;\n\napi$3.shouldHandleInput = input => matchers$2.hex8.test(input) || matchers$2.hex4.test(input);\n\napi$3.toRgb = input => hexToRgba$1(input);\n\napi$3.toRaw = rgba => rgba;\n\napi$3.toString = rgba => {\n if (api$3.wanted === 'hex4') {\n return hexToString$1(rgba, true);\n }\n\n if (api$3.wanted === 'hex8') {\n return hexToString$1(rgba);\n }\n\n if (hasAlpha(rgba)) {\n return api$3.opts.alphaFormat === 'hex' ? hexToString$1(rgba) : api$3.print(api$3.opts.alphaFormat, rgba);\n }\n\n return hexToString$1(rgba);\n};\n\nconst api$4 = TinyColor.registerFormat('hsl');\n\nconst matchers$3 = function () {\n return {\n hsl: new RegExp(`hsl${PERMISSIVE_MATCH3}`),\n hsla: new RegExp(`hsla${PERMISSIVE_MATCH4}`)\n };\n}();\n\nconst isValidCSSUnitHSL = hsl => isValidCSSUnit(hsl.h) && isValidCSSUnit(hsl.s) && isValidCSSUnit(hsl.l);\n\nfunction rgbaToHsla(rgba) {\n const r = bound01(rgba.r, 255);\n const g = bound01(rgba.g, 255);\n const b = bound01(rgba.b, 255);\n const a = rgba.a || 1;\n const max = mathMax(r, g, b);\n const min = mathMin(r, g, b);\n let h, s;\n const l = (max + min) / 2;\n\n if (max === min) {\n h = 0;\n s = 0;\n } else {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n\n case g:\n h = (b - r) / d + 2;\n break;\n\n default:\n h = (r - g) / d + 4;\n break;\n }\n\n h /= 6;\n }\n\n return {\n h,\n s,\n l,\n a\n };\n}\n\nfunction hslaToRgba(hsla) {\n const h = bound01(hsla.h, 360);\n const s = bound01(convertToPercentage(hsla.s), 100);\n const l = bound01(convertToPercentage(hsla.l), 100);\n const a = hsla.a || 1;\n let r, g, b;\n\n function hue2rgb(p, q, t) {\n t = t < 0 ? t + 1 : t;\n t = t > 1 ? t - 1 : t;\n\n if (t < 1 / 6) {\n return p + (q - p) * 6 * t;\n }\n\n if (t < 1 / 2) {\n return q;\n }\n\n if (t < 2 / 3) {\n return p + (q - p) * (2 / 3 - t) * 6;\n }\n\n return p;\n }\n\n if (s === 0) {\n r = l;\n g = l;\n b = l;\n } else {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n\n return {\n r: r * 255,\n g: g * 255,\n b: b * 255,\n a\n };\n}\n\nfunction hslStringToObject(color) {\n let h, s, l, a, match;\n\n if (match = matchers$3.hsl.exec(color)) {\n [h, s, l] = match.splice(1, 3);\n return {\n h,\n s,\n l\n };\n }\n\n if (match = matchers$3.hsla.exec(color)) {\n [h, s, l, a] = match.splice(1, 4);\n return {\n h,\n s,\n l,\n a\n };\n }\n\n return false;\n}\n\nfunction hslaToString(hsla) {\n let {\n h,\n s,\n l,\n a\n } = hsla;\n h = mathRound(h * 360);\n s = mathRound(s * 100);\n l = mathRound(l * 100);\n return a === 1 ? `hsl(${h}, ${s}%, ${l}%)` : `hsla(${h}, ${s}%, ${l}%, ${a})`;\n}\n\nfunction hslaToRaw(hsla) {\n let {\n h,\n s,\n l,\n a\n } = hsla;\n h *= 360;\n return {\n h,\n s,\n l,\n a\n };\n}\n\napi$4.shouldHandleInput = input => typeof input === 'object' && isValidCSSUnitHSL(input) || hslStringToObject(input);\n\napi$4.toRgb = input => typeof input === 'object' && hslaToRgba(input) || hslaToRgba(hslStringToObject(input));\n\napi$4.toRaw = rgba => hslaToRaw(rgbaToHsla(rgba));\n\napi$4.toString = rgba => hslaToString(rgbaToHsla(rgba));\n\nconst api$5 = TinyColor.registerFormat('hsv');\n\nconst matchers$4 = function () {\n return {\n hsv: new RegExp(`hsv${PERMISSIVE_MATCH3}`),\n hsva: new RegExp(`hsva${PERMISSIVE_MATCH4}`)\n };\n}();\n\nconst isValidCSSUnitHSV = hsv => isValidCSSUnit(hsv.h) && isValidCSSUnit(hsv.s) && isValidCSSUnit(hsv.v);\n\nfunction rgbaToHsva(rgba) {\n const r = bound01(rgba.r, 255);\n const g = bound01(rgba.g, 255);\n const b = bound01(rgba.b, 255);\n const a = rgba.a || 1;\n const max = mathMax(r, g, b);\n const min = mathMin(r, g, b);\n const d = max - min;\n let h;\n const s = max === 0 ? 0 : d / max;\n const v = max;\n\n if (max === min) {\n h = 0;\n } else {\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n\n case g:\n h = (b - r) / d + 2;\n break;\n\n default:\n h = (r - g) / d + 4;\n break;\n }\n\n h /= 6;\n }\n\n return {\n h,\n s,\n v,\n a\n };\n}\n\nfunction hsvaToRgba(hsva) {\n const h = bound01(hsva.h, 360) * 6;\n const s = bound01(convertToPercentage(hsva.s), 100);\n const v = bound01(convertToPercentage(hsva.v), 100);\n const a = hsva.a || 1;\n const i = Math.floor(h);\n const f = h - i;\n const p = v * (1 - s);\n const q = v * (1 - f * s);\n const t = v * (1 - (1 - f) * s);\n const mod = i % 6;\n const r = [v, q, p, p, t, v][mod];\n const g = [t, v, v, q, p, p][mod];\n const b = [p, p, t, v, v, q][mod];\n return {\n r: r * 255,\n g: g * 255,\n b: b * 255,\n a\n };\n}\n\nfunction hsvStringToObject(color) {\n let h, s, v, a, match;\n\n if (match = matchers$4.hsv.exec(color)) {\n [h, s, v] = match.splice(1, 3);\n return {\n h,\n s,\n v\n };\n }\n\n if (match = matchers$4.hsva.exec(color)) {\n [h, s, v, a] = match.splice(1, 4);\n return {\n h,\n s,\n v,\n a\n };\n }\n\n return false;\n}\n\nfunction hsvaToString(hsva) {\n let {\n h,\n s,\n v,\n a\n } = hsva;\n h = mathRound(h * 360);\n s = mathRound(s * 100);\n v = mathRound(v * 100);\n return a === 1 ? `hsv(${h}, ${s}%, ${v}%)` : `hsva(${h}, ${s}%, ${v}%, ${a})`;\n}\n\nfunction hsvaToRaw(hsla) {\n let {\n h,\n s,\n v,\n a\n } = hsla;\n h *= 360;\n return {\n h,\n s,\n v,\n a\n };\n}\n\napi$5.shouldHandleInput = input => typeof input === 'object' && isValidCSSUnitHSV(input) || hsvStringToObject(input);\n\napi$5.toRgb = input => typeof input === 'object' && hsvaToRgba(input) || hsvaToRgba(hsvStringToObject(input));\n\napi$5.toRaw = rgba => hsvaToRaw(rgbaToHsva(rgba));\n\napi$5.toString = rgba => hsvaToString(rgbaToHsva(rgba));\n\nconst api$6 = TinyColor.registerFormat('name', {\n alias: ['toName']\n});\n\nfunction flip(o) {\n const flipped = {};\n\n for (const i in o) {\n if ({}.hasOwnProperty.call(o, i)) {\n flipped[o[i]] = i;\n }\n }\n\n return flipped;\n}\n\nconst names = {\n aliceblue: 'f0f8ff',\n antiquewhite: 'faebd7',\n aqua: '0ff',\n aquamarine: '7fffd4',\n azure: 'f0ffff',\n beige: 'f5f5dc',\n bisque: 'ffe4c4',\n black: '000',\n blanchedalmond: 'ffebcd',\n blue: '00f',\n blueviolet: '8a2be2',\n brown: 'a52a2a',\n burlywood: 'deb887',\n burntsienna: 'ea7e5d',\n cadetblue: '5f9ea0',\n chartreuse: '7fff00',\n chocolate: 'd2691e',\n coral: 'ff7f50',\n cornflowerblue: '6495ed',\n cornsilk: 'fff8dc',\n crimson: 'dc143c',\n cyan: '0ff',\n darkblue: '00008b',\n darkcyan: '008b8b',\n darkgoldenrod: 'b8860b',\n darkgray: 'a9a9a9',\n darkgreen: '006400',\n darkgrey: 'a9a9a9',\n darkkhaki: 'bdb76b',\n darkmagenta: '8b008b',\n darkolivegreen: '556b2f',\n darkorange: 'ff8c00',\n darkorchid: '9932cc',\n darkred: '8b0000',\n darksalmon: 'e9967a',\n darkseagreen: '8fbc8f',\n darkslateblue: '483d8b',\n darkslategray: '2f4f4f',\n darkslategrey: '2f4f4f',\n darkturquoise: '00ced1',\n darkviolet: '9400d3',\n deeppink: 'ff1493',\n deepskyblue: '00bfff',\n dimgray: '696969',\n dimgrey: '696969',\n dodgerblue: '1e90ff',\n firebrick: 'b22222',\n floralwhite: 'fffaf0',\n forestgreen: '228b22',\n fuchsia: 'f0f',\n gainsboro: 'dcdcdc',\n ghostwhite: 'f8f8ff',\n gold: 'ffd700',\n goldenrod: 'daa520',\n gray: '808080',\n green: '008000',\n greenyellow: 'adff2f',\n grey: '808080',\n honeydew: 'f0fff0',\n hotpink: 'ff69b4',\n indianred: 'cd5c5c',\n indigo: '4b0082',\n ivory: 'fffff0',\n khaki: 'f0e68c',\n lavender: 'e6e6fa',\n lavenderblush: 'fff0f5',\n lawngreen: '7cfc00',\n lemonchiffon: 'fffacd',\n lightblue: 'add8e6',\n lightcoral: 'f08080',\n lightcyan: 'e0ffff',\n lightgoldenrodyellow: 'fafad2',\n lightgray: 'd3d3d3',\n lightgreen: '90ee90',\n lightgrey: 'd3d3d3',\n lightpink: 'ffb6c1',\n lightsalmon: 'ffa07a',\n lightseagreen: '20b2aa',\n lightskyblue: '87cefa',\n lightslategray: '789',\n lightslategrey: '789',\n lightsteelblue: 'b0c4de',\n lightyellow: 'ffffe0',\n lime: '0f0',\n limegreen: '32cd32',\n linen: 'faf0e6',\n magenta: 'f0f',\n maroon: '800000',\n mediumaquamarine: '66cdaa',\n mediumblue: '0000cd',\n mediumorchid: 'ba55d3',\n mediumpurple: '9370db',\n mediumseagreen: '3cb371',\n mediumslateblue: '7b68ee',\n mediumspringgreen: '00fa9a',\n mediumturquoise: '48d1cc',\n mediumvioletred: 'c71585',\n midnightblue: '191970',\n mintcream: 'f5fffa',\n mistyrose: 'ffe4e1',\n moccasin: 'ffe4b5',\n navajowhite: 'ffdead',\n navy: '000080',\n oldlace: 'fdf5e6',\n olive: '808000',\n olivedrab: '6b8e23',\n orange: 'ffa500',\n orangered: 'ff4500',\n orchid: 'da70d6',\n palegoldenrod: 'eee8aa',\n palegreen: '98fb98',\n paleturquoise: 'afeeee',\n palevioletred: 'db7093',\n papayawhip: 'ffefd5',\n peachpuff: 'ffdab9',\n peru: 'cd853f',\n pink: 'ffc0cb',\n plum: 'dda0dd',\n powderblue: 'b0e0e6',\n purple: '800080',\n rebeccapurple: '639',\n red: 'f00',\n rosybrown: 'bc8f8f',\n royalblue: '4169e1',\n saddlebrown: '8b4513',\n salmon: 'fa8072',\n sandybrown: 'f4a460',\n seagreen: '2e8b57',\n seashell: 'fff5ee',\n sienna: 'a0522d',\n silver: 'c0c0c0',\n skyblue: '87ceeb',\n slateblue: '6a5acd',\n slategray: '708090',\n slategrey: '708090',\n snow: 'fffafa',\n springgreen: '00ff7f',\n steelblue: '4682b4',\n tan: 'd2b48c',\n teal: '008080',\n thistle: 'd8bfd8',\n tomato: 'ff6347',\n turquoise: '40e0d0',\n violet: 'ee82ee',\n wheat: 'f5deb3',\n white: 'fff',\n whitesmoke: 'f5f5f5',\n yellow: 'ff0',\n yellowgreen: '9acd32'\n};\nnames.transparent = '00000000';\nconst hexNames = flip(names);\n\napi$6.shouldHandleInput = input => names[input];\n\napi$6.toRgb = input => api$6.parse(names[input]).rgba;\n\napi$6.toRaw = rgba => rgba;\n\napi$6.toString = rgba => {\n if (rgba.a === 0) {\n return 'transparent';\n }\n\n if (hasAlpha(rgba) && api$6.wanted === 'toName') {\n return false;\n }\n\n if (hasAlpha(rgba) && api$6.wanted === 'name') {\n return `#${rgbToHex(rgba)}`;\n }\n\n if (hasAlpha(rgba)) {\n return api$6.print(api$6.opts.alphaFormat, rgba);\n }\n\n return hexNames[rgbToHex(rgba, true)] || false;\n};\n\nfunction tinycolor(color, opts) {\n return new TinyColor(color, opts);\n}\n\ntinycolor.equals = TinyColor.equals;\ntinycolor.registerFormat = TinyColor.registerFormat;\ntinycolor.fromRatio = TinyColor.fromRatio;\ntinycolor.mix = TinyColor.mix;\ntinycolor.readability = TinyColor.readability;\ntinycolor.isReadable = TinyColor.isReadable;\ntinycolor.mostReadable = TinyColor.mostReadable;\ntinycolor.names = names;\n\nexport { TinyColor, names, tinycolor };\n", "import { tinycolor } from \"@thebespokepixel/es-tinycolor\";\n\n/**\n *\n * @typedef {String} hexColor a string starting with a # followed by 6 hex characters\n */\n\n/**\n * Adds CSS to the document\n * that defines custom CSS color variables for the given colors.\n * The variables look like --color-, e.g. --color-primary-70.\n *\n * text/primary/highlight have additional color shades that are computed:\n * color (100), 90, 80, 70, 60, 50, 40, 20, 10 4.\n *\n * @param {object} [options]\n * @param {object} [options.colors] {: }\n * @param {hexColor} [options.colors.primary-70]\n * @param {hexColor} [options.colors.highlight-70]\n * @param {hexColor} [options.colors.text]\n * @param {hexColor} [options.colors.background]\n * @param {String} [options.selector] the CSS selector to wrap the variables in (default: :root)\n * @param {String} [options.styleElementSelector] A CSS selector pointing to a