Your IP : 216.73.216.52


Current Path : /proc/thread-self/cwd/static/frontend/Magento/blank/it_IT/js/bundle/
Upload File :
Current File : //proc/thread-self/cwd/static/frontend/Magento/blank/it_IT/js/bundle/bundle7.js

require.config({"config": {
        "jsbuild":{"jquery/spectrum/spectrum.js":"// Spectrum Colorpicker v1.8.1\n// https://github.com/bgrins/spectrum\n// Author: Brian Grinstead\n// License: MIT\n\n(function (factory) {\n    \"use strict\";\n\n    if (typeof define === 'function' && define.amd) { // AMD\n        define(['jquery'], factory);\n    }\n    else if (typeof exports == \"object\" && typeof module == \"object\") { // CommonJS\n        module.exports = factory(require('jquery'));\n    }\n    else { // Browser\n        factory(jQuery);\n    }\n})(function($, undefined) {\n    \"use strict\";\n\n    var defaultOpts = {\n\n            // Callbacks\n            beforeShow: noop,\n            move: noop,\n            change: noop,\n            show: noop,\n            hide: noop,\n\n            // Options\n            color: false,\n            flat: false,\n            showInput: false,\n            allowEmpty: false,\n            showButtons: true,\n            clickoutFiresChange: true,\n            showInitial: false,\n            showPalette: false,\n            showPaletteOnly: false,\n            hideAfterPaletteSelect: false,\n            togglePaletteOnly: false,\n            showSelectionPalette: true,\n            localStorageKey: false,\n            appendTo: \"body\",\n            maxSelectionSize: 7,\n            cancelText: \"cancel\",\n            chooseText: \"choose\",\n            togglePaletteMoreText: \"more\",\n            togglePaletteLessText: \"less\",\n            clearText: \"Clear Color Selection\",\n            noColorSelectedText: \"No Color Selected\",\n            preferredFormat: false,\n            className: \"\", // Deprecated - use containerClassName and replacerClassName instead.\n            containerClassName: \"\",\n            replacerClassName: \"\",\n            showAlpha: false,\n            theme: \"sp-light\",\n            palette: [[\"#ffffff\", \"#000000\", \"#ff0000\", \"#ff8000\", \"#ffff00\", \"#008000\", \"#0000ff\", \"#4b0082\", \"#9400d3\"]],\n            selectionPalette: [],\n            disabled: false,\n            offset: null\n        },\n        spectrums = [],\n        IE = !!/msie/i.exec( window.navigator.userAgent ),\n        rgbaSupport = (function() {\n            function contains( str, substr ) {\n                return !!~('' + str).indexOf(substr);\n            }\n\n            var elem = document.createElement('div');\n            var style = elem.style;\n            style.cssText = 'background-color:rgba(0,0,0,.5)';\n            return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');\n        })(),\n        replaceInput = [\n            \"<div class='sp-replacer'>\",\n            \"<div class='sp-preview'><div class='sp-preview-inner'></div></div>\",\n            \"<div class='sp-dd'>&#9660;</div>\",\n            \"</div>\"\n        ].join(''),\n        markup = (function () {\n\n            // IE does not support gradients with multiple stops, so we need to simulate\n            //  that for the rainbow slider with 8 divs that each have a single gradient\n            var gradientFix = \"\";\n            if (IE) {\n                for (var i = 1; i <= 6; i++) {\n                    gradientFix += \"<div class='sp-\" + i + \"'></div>\";\n                }\n            }\n\n            return [\n                \"<div class='sp-container sp-hidden'>\",\n                \"<div class='sp-palette-container'>\",\n                \"<div class='sp-palette sp-thumb sp-cf'></div>\",\n                \"<div class='sp-palette-button-container sp-cf'>\",\n                \"<button type='button' class='sp-palette-toggle'></button>\",\n                \"</div>\",\n                \"</div>\",\n                \"<div class='sp-picker-container'>\",\n                \"<div class='sp-top sp-cf'>\",\n                \"<div class='sp-fill'></div>\",\n                \"<div class='sp-top-inner'>\",\n                \"<div class='sp-color'>\",\n                \"<div class='sp-sat'>\",\n                \"<div class='sp-val'>\",\n                \"<div class='sp-dragger'></div>\",\n                \"</div>\",\n                \"</div>\",\n                \"</div>\",\n                \"<div class='sp-clear sp-clear-display'>\",\n                \"</div>\",\n                \"<div class='sp-hue'>\",\n                \"<div class='sp-slider'></div>\",\n                gradientFix,\n                \"</div>\",\n                \"</div>\",\n                \"<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>\",\n                \"</div>\",\n                \"<div class='sp-input-container sp-cf'>\",\n                \"<input class='sp-input' type='text' spellcheck='false'  />\",\n                \"</div>\",\n                \"<div class='sp-initial sp-thumb sp-cf'></div>\",\n                \"<div class='sp-button-container sp-cf'>\",\n                \"<a class='sp-cancel' href='#'></a>\",\n                \"<button type='button' class='sp-choose'></button>\",\n                \"</div>\",\n                \"</div>\",\n                \"</div>\"\n            ].join(\"\");\n        })();\n\n    function paletteTemplate (p, color, className, opts) {\n        var html = [];\n        for (var i = 0; i < p.length; i++) {\n            var current = p[i];\n            if(current) {\n                var tiny = tinycolor(current);\n                var c = tiny.toHsl().l < 0.5 ? \"sp-thumb-el sp-thumb-dark\" : \"sp-thumb-el sp-thumb-light\";\n                c += (tinycolor.equals(color, current)) ? \" sp-thumb-active\" : \"\";\n                var formattedString = tiny.toString(opts.preferredFormat || \"rgb\");\n                var swatchStyle = rgbaSupport ? (\"background-color:\" + tiny.toRgbString()) : \"filter:\" + tiny.toFilter();\n                html.push('<span title=\"' + formattedString + '\" data-color=\"' + tiny.toRgbString() + '\" class=\"' + c + '\"><span class=\"sp-thumb-inner\" style=\"' + swatchStyle + ';\"></span></span>');\n            } else {\n                var cls = 'sp-clear-display';\n                html.push($('<div />')\n                    .append($('<span data-color=\"\" style=\"background-color:transparent;\" class=\"' + cls + '\"></span>')\n                        .attr('title', opts.noColorSelectedText)\n                    )\n                    .html()\n                );\n            }\n        }\n        return \"<div class='sp-cf \" + className + \"'>\" + html.join('') + \"</div>\";\n    }\n\n    function hideAll() {\n        for (var i = 0; i < spectrums.length; i++) {\n            if (spectrums[i]) {\n                spectrums[i].hide();\n            }\n        }\n    }\n\n    function instanceOptions(o, callbackContext) {\n        var opts = $.extend({}, defaultOpts, o);\n        opts.callbacks = {\n            'move': bind(opts.move, callbackContext),\n            'change': bind(opts.change, callbackContext),\n            'show': bind(opts.show, callbackContext),\n            'hide': bind(opts.hide, callbackContext),\n            'beforeShow': bind(opts.beforeShow, callbackContext)\n        };\n\n        return opts;\n    }\n\n    function spectrum(element, o) {\n\n        var opts = instanceOptions(o, element),\n            flat = opts.flat,\n            showSelectionPalette = opts.showSelectionPalette,\n            localStorageKey = opts.localStorageKey,\n            theme = opts.theme,\n            callbacks = opts.callbacks,\n            resize = throttle(reflow, 10),\n            visible = false,\n            isDragging = false,\n            dragWidth = 0,\n            dragHeight = 0,\n            dragHelperHeight = 0,\n            slideHeight = 0,\n            slideWidth = 0,\n            alphaWidth = 0,\n            alphaSlideHelperWidth = 0,\n            slideHelperHeight = 0,\n            currentHue = 0,\n            currentSaturation = 0,\n            currentValue = 0,\n            currentAlpha = 1,\n            palette = [],\n            paletteArray = [],\n            paletteLookup = {},\n            selectionPalette = opts.selectionPalette.slice(0),\n            maxSelectionSize = opts.maxSelectionSize,\n            draggingClass = \"sp-dragging\",\n            shiftMovementDirection = null;\n\n        var doc = element.ownerDocument,\n            body = doc.body,\n            boundElement = $(element),\n            disabled = false,\n            container = $(markup, doc).addClass(theme),\n            pickerContainer = container.find(\".sp-picker-container\"),\n            dragger = container.find(\".sp-color\"),\n            dragHelper = container.find(\".sp-dragger\"),\n            slider = container.find(\".sp-hue\"),\n            slideHelper = container.find(\".sp-slider\"),\n            alphaSliderInner = container.find(\".sp-alpha-inner\"),\n            alphaSlider = container.find(\".sp-alpha\"),\n            alphaSlideHelper = container.find(\".sp-alpha-handle\"),\n            textInput = container.find(\".sp-input\"),\n            paletteContainer = container.find(\".sp-palette\"),\n            initialColorContainer = container.find(\".sp-initial\"),\n            cancelButton = container.find(\".sp-cancel\"),\n            clearButton = container.find(\".sp-clear\"),\n            chooseButton = container.find(\".sp-choose\"),\n            toggleButton = container.find(\".sp-palette-toggle\"),\n            isInput = boundElement.is(\"input\"),\n            isInputTypeColor = isInput && boundElement.attr(\"type\") === \"color\" && inputTypeColorSupport(),\n            shouldReplace = isInput && !flat,\n            replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),\n            offsetElement = (shouldReplace) ? replacer : boundElement,\n            previewElement = replacer.find(\".sp-preview-inner\"),\n            initialColor = opts.color || (isInput && boundElement.val()),\n            colorOnShow = false,\n            currentPreferredFormat = opts.preferredFormat,\n            clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,\n            isEmpty = !initialColor,\n            allowEmpty = opts.allowEmpty && !isInputTypeColor;\n\n        function applyOptions() {\n\n            if (opts.showPaletteOnly) {\n                opts.showPalette = true;\n            }\n\n            toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);\n\n            if (opts.palette) {\n                palette = opts.palette.slice(0);\n                paletteArray = $.isArray(palette[0]) ? palette : [palette];\n                paletteLookup = {};\n                for (var i = 0; i < paletteArray.length; i++) {\n                    for (var j = 0; j < paletteArray[i].length; j++) {\n                        var rgb = tinycolor(paletteArray[i][j]).toRgbString();\n                        paletteLookup[rgb] = true;\n                    }\n                }\n            }\n\n            container.toggleClass(\"sp-flat\", flat);\n            container.toggleClass(\"sp-input-disabled\", !opts.showInput);\n            container.toggleClass(\"sp-alpha-enabled\", opts.showAlpha);\n            container.toggleClass(\"sp-clear-enabled\", allowEmpty);\n            container.toggleClass(\"sp-buttons-disabled\", !opts.showButtons);\n            container.toggleClass(\"sp-palette-buttons-disabled\", !opts.togglePaletteOnly);\n            container.toggleClass(\"sp-palette-disabled\", !opts.showPalette);\n            container.toggleClass(\"sp-palette-only\", opts.showPaletteOnly);\n            container.toggleClass(\"sp-initial-disabled\", !opts.showInitial);\n            container.addClass(opts.className).addClass(opts.containerClassName);\n\n            reflow();\n        }\n\n        function initialize() {\n\n            if (IE) {\n                container.find(\"*:not(input)\").attr(\"unselectable\", \"on\");\n            }\n\n            applyOptions();\n\n            if (shouldReplace) {\n                boundElement.after(replacer).hide();\n            }\n\n            if (!allowEmpty) {\n                clearButton.hide();\n            }\n\n            if (flat) {\n                boundElement.after(container).hide();\n            }\n            else {\n\n                var appendTo = opts.appendTo === \"parent\" ? boundElement.parent() : $(opts.appendTo);\n                if (appendTo.length !== 1) {\n                    appendTo = $(\"body\");\n                }\n\n                appendTo.append(container);\n            }\n\n            updateSelectionPaletteFromStorage();\n\n            offsetElement.on(\"click.spectrum touchstart.spectrum\", function (e) {\n                if (!disabled) {\n                    toggle();\n                }\n\n                e.stopPropagation();\n\n                if (!$(e.target).is(\"input\")) {\n                    e.preventDefault();\n                }\n            });\n\n            if(boundElement.is(\":disabled\") || (opts.disabled === true)) {\n                disable();\n            }\n\n            // Prevent clicks from bubbling up to document.  This would cause it to be hidden.\n            container.click(stopPropagation);\n\n            // Handle user typed input\n            textInput.change(setFromTextInput);\n            textInput.on(\"paste\", function () {\n                setTimeout(setFromTextInput, 1);\n            });\n            textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });\n\n            cancelButton.text(opts.cancelText);\n            cancelButton.on(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                revert();\n                hide();\n            });\n\n            clearButton.attr(\"title\", opts.clearText);\n            clearButton.on(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                isEmpty = true;\n                move();\n\n                if(flat) {\n                    //for the flat style, this is a change event\n                    updateOriginalInput(true);\n                }\n            });\n\n            chooseButton.text(opts.chooseText);\n            chooseButton.on(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n\n                if (IE && textInput.is(\":focus\")) {\n                    textInput.trigger('change');\n                }\n\n                if (isValid()) {\n                    updateOriginalInput(true);\n                    hide();\n                }\n            });\n\n            toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);\n            toggleButton.on(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n\n                opts.showPaletteOnly = !opts.showPaletteOnly;\n\n                // To make sure the Picker area is drawn on the right, next to the\n                // Palette area (and not below the palette), first move the Palette\n                // to the left to make space for the picker, plus 5px extra.\n                // The 'applyOptions' function puts the whole container back into place\n                // and takes care of the button-text and the sp-palette-only CSS class.\n                if (!opts.showPaletteOnly && !flat) {\n                    container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5));\n                }\n                applyOptions();\n            });\n\n            draggable(alphaSlider, function (dragX, dragY, e) {\n                currentAlpha = (dragX / alphaWidth);\n                isEmpty = false;\n                if (e.shiftKey) {\n                    currentAlpha = Math.round(currentAlpha * 10) / 10;\n                }\n\n                move();\n            }, dragStart, dragStop);\n\n            draggable(slider, function (dragX, dragY) {\n                currentHue = parseFloat(dragY / slideHeight);\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n                move();\n            }, dragStart, dragStop);\n\n            draggable(dragger, function (dragX, dragY, e) {\n\n                // shift+drag should snap the movement to either the x or y axis.\n                if (!e.shiftKey) {\n                    shiftMovementDirection = null;\n                }\n                else if (!shiftMovementDirection) {\n                    var oldDragX = currentSaturation * dragWidth;\n                    var oldDragY = dragHeight - (currentValue * dragHeight);\n                    var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);\n\n                    shiftMovementDirection = furtherFromX ? \"x\" : \"y\";\n                }\n\n                var setSaturation = !shiftMovementDirection || shiftMovementDirection === \"x\";\n                var setValue = !shiftMovementDirection || shiftMovementDirection === \"y\";\n\n                if (setSaturation) {\n                    currentSaturation = parseFloat(dragX / dragWidth);\n                }\n                if (setValue) {\n                    currentValue = parseFloat((dragHeight - dragY) / dragHeight);\n                }\n\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n\n                move();\n\n            }, dragStart, dragStop);\n\n            if (!!initialColor) {\n                set(initialColor);\n\n                // In case color was black - update the preview UI and set the format\n                // since the set function will not run (default color is black).\n                updateUI();\n                currentPreferredFormat = opts.preferredFormat || tinycolor(initialColor).format;\n\n                addColorToSelectionPalette(initialColor);\n            }\n            else {\n                updateUI();\n            }\n\n            if (flat) {\n                show();\n            }\n\n            function paletteElementClick(e) {\n                if (e.data && e.data.ignore) {\n                    set($(e.target).closest(\".sp-thumb-el\").data(\"color\"));\n                    move();\n                }\n                else {\n                    set($(e.target).closest(\".sp-thumb-el\").data(\"color\"));\n                    move();\n\n                    updateOriginalInput(true);\n                    if (opts.hideAfterPaletteSelect) {\n                        hide();\n                    }\n                }\n\n                return false;\n            }\n\n            var paletteEvent = IE ? \"mousedown.spectrum\" : \"click.spectrum touchstart.spectrum\";\n            paletteContainer.on(paletteEvent, \".sp-thumb-el\", paletteElementClick);\n            initialColorContainer.on(paletteEvent, \".sp-thumb-el:nth-child(1)\", { ignore: true }, paletteElementClick);\n        }\n\n        function updateSelectionPaletteFromStorage() {\n\n            if (localStorageKey && window.localStorage) {\n\n                // Migrate old palettes over to new format.  May want to remove this eventually.\n                try {\n                    var oldPalette = window.localStorage[localStorageKey].split(\",#\");\n                    if (oldPalette.length > 1) {\n                        delete window.localStorage[localStorageKey];\n                        $.each(oldPalette, function(i, c) {\n                            addColorToSelectionPalette(c);\n                        });\n                    }\n                }\n                catch(e) { }\n\n                try {\n                    selectionPalette = window.localStorage[localStorageKey].split(\";\");\n                }\n                catch (e) { }\n            }\n        }\n\n        function addColorToSelectionPalette(color) {\n            if (showSelectionPalette) {\n                var rgb = tinycolor(color).toRgbString();\n                if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {\n                    selectionPalette.push(rgb);\n                    while(selectionPalette.length > maxSelectionSize) {\n                        selectionPalette.shift();\n                    }\n                }\n\n                if (localStorageKey && window.localStorage) {\n                    try {\n                        window.localStorage[localStorageKey] = selectionPalette.join(\";\");\n                    }\n                    catch(e) { }\n                }\n            }\n        }\n\n        function getUniqueSelectionPalette() {\n            var unique = [];\n            if (opts.showPalette) {\n                for (var i = 0; i < selectionPalette.length; i++) {\n                    var rgb = tinycolor(selectionPalette[i]).toRgbString();\n\n                    if (!paletteLookup[rgb]) {\n                        unique.push(selectionPalette[i]);\n                    }\n                }\n            }\n\n            return unique.reverse().slice(0, opts.maxSelectionSize);\n        }\n\n        function drawPalette() {\n\n            var currentColor = get();\n\n            var html = $.map(paletteArray, function (palette, i) {\n                return paletteTemplate(palette, currentColor, \"sp-palette-row sp-palette-row-\" + i, opts);\n            });\n\n            updateSelectionPaletteFromStorage();\n\n            if (selectionPalette) {\n                html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, \"sp-palette-row sp-palette-row-selection\", opts));\n            }\n\n            paletteContainer.html(html.join(\"\"));\n        }\n\n        function drawInitial() {\n            if (opts.showInitial) {\n                var initial = colorOnShow;\n                var current = get();\n                initialColorContainer.html(paletteTemplate([initial, current], current, \"sp-palette-row-initial\", opts));\n            }\n        }\n\n        function dragStart() {\n            if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {\n                reflow();\n            }\n            isDragging = true;\n            container.addClass(draggingClass);\n            shiftMovementDirection = null;\n            boundElement.trigger('dragstart.spectrum', [ get() ]);\n        }\n\n        function dragStop() {\n            isDragging = false;\n            container.removeClass(draggingClass);\n            boundElement.trigger('dragstop.spectrum', [ get() ]);\n        }\n\n        function setFromTextInput() {\n\n            var value = textInput.val();\n\n            if ((value === null || value === \"\") && allowEmpty) {\n                set(null);\n                move();\n                updateOriginalInput();\n            }\n            else {\n                var tiny = tinycolor(value);\n                if (tiny.isValid()) {\n                    set(tiny);\n                    move();\n                    updateOriginalInput(true);\n                }\n                else {\n                    textInput.addClass(\"sp-validation-error\");\n                }\n            }\n        }\n\n        function toggle() {\n            if (visible) {\n                hide();\n            }\n            else {\n                show();\n            }\n        }\n\n        function show() {\n            var event = $.Event('beforeShow.spectrum');\n\n            if (visible) {\n                reflow();\n                return;\n            }\n\n            boundElement.trigger(event, [ get() ]);\n\n            if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {\n                return;\n            }\n\n            hideAll();\n            visible = true;\n\n            $(doc).on(\"keydown.spectrum\", onkeydown);\n            $(doc).on(\"click.spectrum\", clickout);\n            $(window).on(\"resize.spectrum\", resize);\n            replacer.addClass(\"sp-active\");\n            container.removeClass(\"sp-hidden\");\n\n            reflow();\n            updateUI();\n\n            colorOnShow = get();\n\n            drawInitial();\n            callbacks.show(colorOnShow);\n            boundElement.trigger('show.spectrum', [ colorOnShow ]);\n        }\n\n        function onkeydown(e) {\n            // Close on ESC\n            if (e.keyCode === 27) {\n                hide();\n            }\n        }\n\n        function clickout(e) {\n            // Return on right click.\n            if (e.button == 2) { return; }\n\n            // If a drag event was happening during the mouseup, don't hide\n            // on click.\n            if (isDragging) { return; }\n\n            if (clickoutFiresChange) {\n                updateOriginalInput(true);\n            }\n            else {\n                revert();\n            }\n            hide();\n        }\n\n        function hide() {\n            // Return if hiding is unnecessary\n            if (!visible || flat) { return; }\n            visible = false;\n\n            $(doc).off(\"keydown.spectrum\", onkeydown);\n            $(doc).off(\"click.spectrum\", clickout);\n            $(window).off(\"resize.spectrum\", resize);\n\n            replacer.removeClass(\"sp-active\");\n            container.addClass(\"sp-hidden\");\n\n            callbacks.hide(get());\n            boundElement.trigger('hide.spectrum', [ get() ]);\n        }\n\n        function revert() {\n            set(colorOnShow, true);\n            updateOriginalInput(true);\n        }\n\n        function set(color, ignoreFormatChange) {\n            if (tinycolor.equals(color, get())) {\n                // Update UI just in case a validation error needs\n                // to be cleared.\n                updateUI();\n                return;\n            }\n\n            var newColor, newHsv;\n            if (!color && allowEmpty) {\n                isEmpty = true;\n            } else {\n                isEmpty = false;\n                newColor = tinycolor(color);\n                newHsv = newColor.toHsv();\n\n                currentHue = (newHsv.h % 360) / 360;\n                currentSaturation = newHsv.s;\n                currentValue = newHsv.v;\n                currentAlpha = newHsv.a;\n            }\n            updateUI();\n\n            if (newColor && newColor.isValid() && !ignoreFormatChange) {\n                currentPreferredFormat = opts.preferredFormat || newColor.getFormat();\n            }\n        }\n\n        function get(opts) {\n            opts = opts || { };\n\n            if (allowEmpty && isEmpty) {\n                return null;\n            }\n\n            return tinycolor.fromRatio({\n                h: currentHue,\n                s: currentSaturation,\n                v: currentValue,\n                a: Math.round(currentAlpha * 1000) / 1000\n            }, { format: opts.format || currentPreferredFormat });\n        }\n\n        function isValid() {\n            return !textInput.hasClass(\"sp-validation-error\");\n        }\n\n        function move() {\n            updateUI();\n\n            callbacks.move(get());\n            boundElement.trigger('move.spectrum', [ get() ]);\n        }\n\n        function updateUI() {\n\n            textInput.removeClass(\"sp-validation-error\");\n\n            updateHelperLocations();\n\n            // Update dragger background color (gradients take care of saturation and value).\n            var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });\n            dragger.css(\"background-color\", flatColor.toHexString());\n\n            // Get a format that alpha will be included in (hex and names ignore alpha)\n            var format = currentPreferredFormat;\n            if (currentAlpha < 1 && !(currentAlpha === 0 && format === \"name\")) {\n                if (format === \"hex\" || format === \"hex3\" || format === \"hex6\" || format === \"name\") {\n                    format = \"rgb\";\n                }\n            }\n\n            var realColor = get({ format: format }),\n                displayColor = '';\n\n            //reset background info for preview element\n            previewElement.removeClass(\"sp-clear-display\");\n            previewElement.css('background-color', 'transparent');\n\n            if (!realColor && allowEmpty) {\n                // Update the replaced elements background with icon indicating no color selection\n                previewElement.addClass(\"sp-clear-display\");\n            }\n            else {\n                var realHex = realColor.toHexString(),\n                    realRgb = realColor.toRgbString();\n\n                // Update the replaced elements background color (with actual selected color)\n                if (rgbaSupport || realColor.alpha === 1) {\n                    previewElement.css(\"background-color\", realRgb);\n                }\n                else {\n                    previewElement.css(\"background-color\", \"transparent\");\n                    previewElement.css(\"filter\", realColor.toFilter());\n                }\n\n                if (opts.showAlpha) {\n                    var rgb = realColor.toRgb();\n                    rgb.a = 0;\n                    var realAlpha = tinycolor(rgb).toRgbString();\n                    var gradient = \"linear-gradient(left, \" + realAlpha + \", \" + realHex + \")\";\n\n                    if (IE) {\n                        alphaSliderInner.css(\"filter\", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));\n                    }\n                    else {\n                        alphaSliderInner.css(\"background\", \"-webkit-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-moz-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-ms-\" + gradient);\n                        // Use current syntax gradient on unprefixed property.\n                        alphaSliderInner.css(\"background\",\n                            \"linear-gradient(to right, \" + realAlpha + \", \" + realHex + \")\");\n                    }\n                }\n\n                displayColor = realColor.toString(format);\n            }\n\n            // Update the text entry input as it changes happen\n            if (opts.showInput) {\n                textInput.val(displayColor);\n            }\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            drawInitial();\n        }\n\n        function updateHelperLocations() {\n            var s = currentSaturation;\n            var v = currentValue;\n\n            if(allowEmpty && isEmpty) {\n                //if selected color is empty, hide the helpers\n                alphaSlideHelper.hide();\n                slideHelper.hide();\n                dragHelper.hide();\n            }\n            else {\n                //make sure helpers are visible\n                alphaSlideHelper.show();\n                slideHelper.show();\n                dragHelper.show();\n\n                // Where to show the little circle in that displays your current selected color\n                var dragX = s * dragWidth;\n                var dragY = dragHeight - (v * dragHeight);\n                dragX = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)\n                );\n                dragY = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)\n                );\n                dragHelper.css({\n                    \"top\": dragY + \"px\",\n                    \"left\": dragX + \"px\"\n                });\n\n                var alphaX = currentAlpha * alphaWidth;\n                alphaSlideHelper.css({\n                    \"left\": (alphaX - (alphaSlideHelperWidth / 2)) + \"px\"\n                });\n\n                // Where to show the bar that displays your current selected hue\n                var slideY = (currentHue) * slideHeight;\n                slideHelper.css({\n                    \"top\": (slideY - slideHelperHeight) + \"px\"\n                });\n            }\n        }\n\n        function updateOriginalInput(fireCallback) {\n            var color = get(),\n                displayColor = '',\n                hasChanged = !tinycolor.equals(color, colorOnShow);\n\n            if (color) {\n                displayColor = color.toString(currentPreferredFormat);\n                // Update the selection palette with the current color\n                addColorToSelectionPalette(color);\n            }\n\n            if (isInput) {\n                boundElement.val(displayColor);\n            }\n\n            if (fireCallback && hasChanged) {\n                callbacks.change(color);\n                boundElement.trigger('change', [ color ]);\n            }\n        }\n\n        function reflow() {\n            if (!visible) {\n                return; // Calculations would be useless and wouldn't be reliable anyways\n            }\n            dragWidth = dragger.width();\n            dragHeight = dragger.height();\n            dragHelperHeight = dragHelper.height();\n            slideWidth = slider.width();\n            slideHeight = slider.height();\n            slideHelperHeight = slideHelper.height();\n            alphaWidth = alphaSlider.width();\n            alphaSlideHelperWidth = alphaSlideHelper.width();\n\n            if (!flat) {\n                container.css(\"position\", \"absolute\");\n                if (opts.offset) {\n                    container.offset(opts.offset);\n                } else {\n                    container.offset(getOffset(container, offsetElement));\n                }\n            }\n\n            updateHelperLocations();\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            boundElement.trigger('reflow.spectrum');\n        }\n\n        function destroy() {\n            boundElement.show();\n            offsetElement.off(\"click.spectrum touchstart.spectrum\");\n            container.remove();\n            replacer.remove();\n            spectrums[spect.id] = null;\n        }\n\n        function option(optionName, optionValue) {\n            if (optionName === undefined) {\n                return $.extend({}, opts);\n            }\n            if (optionValue === undefined) {\n                return opts[optionName];\n            }\n\n            opts[optionName] = optionValue;\n\n            if (optionName === \"preferredFormat\") {\n                currentPreferredFormat = opts.preferredFormat;\n            }\n            applyOptions();\n        }\n\n        function enable() {\n            disabled = false;\n            boundElement.attr(\"disabled\", false);\n            offsetElement.removeClass(\"sp-disabled\");\n        }\n\n        function disable() {\n            hide();\n            disabled = true;\n            boundElement.attr(\"disabled\", true);\n            offsetElement.addClass(\"sp-disabled\");\n        }\n\n        function setOffset(coord) {\n            opts.offset = coord;\n            reflow();\n        }\n\n        initialize();\n\n        var spect = {\n            show: show,\n            hide: hide,\n            toggle: toggle,\n            reflow: reflow,\n            option: option,\n            enable: enable,\n            disable: disable,\n            offset: setOffset,\n            set: function (c) {\n                set(c);\n                updateOriginalInput();\n            },\n            get: get,\n            destroy: destroy,\n            container: container\n        };\n\n        spect.id = spectrums.push(spect) - 1;\n\n        return spect;\n    }\n\n    /**\n     * checkOffset - get the offset below/above and left/right element depending on screen position\n     * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js\n     */\n    function getOffset(picker, input) {\n        var extraY = 0;\n        var dpWidth = picker.outerWidth();\n        var dpHeight = picker.outerHeight();\n        var inputHeight = input.outerHeight();\n        var doc = picker[0].ownerDocument;\n        var docElem = doc.documentElement;\n        var viewWidth = docElem.clientWidth + $(doc).scrollLeft();\n        var viewHeight = docElem.clientHeight + $(doc).scrollTop();\n        var offset = input.offset();\n        var offsetLeft = offset.left;\n        var offsetTop = offset.top;\n\n        offsetTop += inputHeight;\n\n        offsetLeft -=\n            Math.min(offsetLeft, (offsetLeft + dpWidth > viewWidth && viewWidth > dpWidth) ?\n                Math.abs(offsetLeft + dpWidth - viewWidth) : 0);\n\n        offsetTop -=\n            Math.min(offsetTop, ((offsetTop + dpHeight > viewHeight && viewHeight > dpHeight) ?\n                Math.abs(dpHeight + inputHeight - extraY) : extraY));\n\n        return {\n            top: offsetTop,\n            bottom: offset.bottom,\n            left: offsetLeft,\n            right: offset.right,\n            width: offset.width,\n            height: offset.height\n        };\n    }\n\n    /**\n     * noop - do nothing\n     */\n    function noop() {\n\n    }\n\n    /**\n     * stopPropagation - makes the code only doing this a little easier to read in line\n     */\n    function stopPropagation(e) {\n        e.stopPropagation();\n    }\n\n    /**\n     * Create a function bound to a given object\n     * Thanks to underscore.js\n     */\n    function bind(func, obj) {\n        var slice = Array.prototype.slice;\n        var args = slice.call(arguments, 2);\n        return function () {\n            return func.apply(obj, args.concat(slice.call(arguments)));\n        };\n    }\n\n    /**\n     * Lightweight drag helper.  Handles containment within the element, so that\n     * when dragging, the x is within [0,element.width] and y is within [0,element.height]\n     */\n    function draggable(element, onmove, onstart, onstop) {\n        onmove = onmove || function () { };\n        onstart = onstart || function () { };\n        onstop = onstop || function () { };\n        var doc = document;\n        var dragging = false;\n        var offset = {};\n        var maxHeight = 0;\n        var maxWidth = 0;\n        var hasTouch = ('ontouchstart' in window);\n\n        var duringDragEvents = {};\n        duringDragEvents[\"selectstart\"] = prevent;\n        duringDragEvents[\"dragstart\"] = prevent;\n        duringDragEvents[\"touchmove mousemove\"] = move;\n        duringDragEvents[\"touchend mouseup\"] = stop;\n\n        function prevent(e) {\n            if (e.stopPropagation) {\n                e.stopPropagation();\n            }\n            if (e.preventDefault) {\n                e.preventDefault();\n            }\n            e.returnValue = false;\n        }\n\n        function move(e) {\n            if (dragging) {\n                // Mouseup happened outside of window\n                if (IE && doc.documentMode < 9 && !e.button) {\n                    return stop();\n                }\n\n                var t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];\n                var pageX = t0 && t0.pageX || e.pageX;\n                var pageY = t0 && t0.pageY || e.pageY;\n\n                var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));\n                var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));\n\n                if (hasTouch) {\n                    // Stop scrolling in iOS\n                    prevent(e);\n                }\n\n                onmove.apply(element, [dragX, dragY, e]);\n            }\n        }\n\n        function start(e) {\n            var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);\n\n            if (!rightclick && !dragging) {\n                if (onstart.apply(element, arguments) !== false) {\n                    dragging = true;\n                    maxHeight = $(element).height();\n                    maxWidth = $(element).width();\n                    offset = $(element).offset();\n\n                    $(doc).on(duringDragEvents);\n                    $(doc.body).addClass(\"sp-dragging\");\n\n                    move(e);\n\n                    prevent(e);\n                }\n            }\n        }\n\n        function stop() {\n            if (dragging) {\n                $(doc).off(duringDragEvents);\n                $(doc.body).removeClass(\"sp-dragging\");\n\n                // Wait a tick before notifying observers to allow the click event\n                // to fire in Chrome.\n                setTimeout(function() {\n                    onstop.apply(element, arguments);\n                }, 0);\n            }\n            dragging = false;\n        }\n\n        $(element).on(\"touchstart mousedown\", start);\n    }\n\n    function throttle(func, wait, debounce) {\n        var timeout;\n        return function () {\n            var context = this, args = arguments;\n            var throttler = function () {\n                timeout = null;\n                func.apply(context, args);\n            };\n            if (debounce) clearTimeout(timeout);\n            if (debounce || !timeout) timeout = setTimeout(throttler, wait);\n        };\n    }\n\n    function inputTypeColorSupport() {\n        return $.fn.spectrum.inputTypeColorSupport();\n    }\n\n    /**\n     * Define a jQuery plugin\n     */\n    var dataID = \"spectrum.id\";\n    $.fn.spectrum = function (opts, extra) {\n\n        if (typeof opts == \"string\") {\n\n            var returnValue = this;\n            var args = Array.prototype.slice.call( arguments, 1 );\n\n            this.each(function () {\n                var spect = spectrums[$(this).data(dataID)];\n                if (spect) {\n                    var method = spect[opts];\n                    if (!method) {\n                        throw new Error( \"Spectrum: no such method: '\" + opts + \"'\" );\n                    }\n\n                    if (opts == \"get\") {\n                        returnValue = spect.get();\n                    }\n                    else if (opts == \"container\") {\n                        returnValue = spect.container;\n                    }\n                    else if (opts == \"option\") {\n                        returnValue = spect.option.apply(spect, args);\n                    }\n                    else if (opts == \"destroy\") {\n                        spect.destroy();\n                        $(this).removeData(dataID);\n                    }\n                    else {\n                        method.apply(spect, args);\n                    }\n                }\n            });\n\n            return returnValue;\n        }\n\n        // Initializing a new instance of spectrum\n        return this.spectrum(\"destroy\").each(function () {\n            var options = $.extend({}, $(this).data(), opts);\n            var spect = spectrum(this, options);\n            $(this).data(dataID, spect.id);\n        });\n    };\n\n    $.fn.spectrum.load = true;\n    $.fn.spectrum.loadOpts = {};\n    $.fn.spectrum.draggable = draggable;\n    $.fn.spectrum.defaults = defaultOpts;\n    $.fn.spectrum.inputTypeColorSupport = function inputTypeColorSupport() {\n        if (typeof inputTypeColorSupport._cachedResult === \"undefined\") {\n            var colorInput = $(\"<input type='color'/>\")[0]; // if color element is supported, value will default to not null\n            inputTypeColorSupport._cachedResult = colorInput.type === \"color\" && colorInput.value !== \"\";\n        }\n        return inputTypeColorSupport._cachedResult;\n    };\n\n    $.spectrum = { };\n    $.spectrum.localization = { };\n    $.spectrum.palettes = { };\n\n    $.fn.spectrum.processNativeColorInputs = function () {\n        var colorInputs = $(\"input[type=color]\");\n        if (colorInputs.length && !inputTypeColorSupport()) {\n            colorInputs.spectrum({\n                preferredFormat: \"hex6\"\n            });\n        }\n    };\n\n    // TinyColor v1.1.2\n    // https://github.com/bgrins/TinyColor\n    // Brian Grinstead, MIT License\n\n    (function() {\n\n        var trimLeft = /^[\\s,#]+/,\n            trimRight = /\\s+$/,\n            tinyCounter = 0,\n            math = Math,\n            mathRound = math.round,\n            mathMin = math.min,\n            mathMax = math.max,\n            mathRandom = math.random;\n\n        var tinycolor = function(color, opts) {\n\n            color = (color) ? color : '';\n            opts = opts || { };\n\n            // If input is already a tinycolor, return itself\n            if (color instanceof tinycolor) {\n                return color;\n            }\n            // If we are called as a function, call using new instead\n            if (!(this instanceof tinycolor)) {\n                return new tinycolor(color, opts);\n            }\n\n            var rgb = inputToRGB(color);\n            this._originalInput = color;\n            this._r = rgb.r;\n            this._g = rgb.g;\n            this._b = rgb.b;\n            this._a = rgb.a;\n            this._roundA = mathRound(1000 * this._a) / 1000;\n            this._format = opts.format || rgb.format;\n            this._gradientType = opts.gradientType;\n\n            // Don't let the range of [0,255] come back in [0,1].\n            // Potentially lose a little bit of precision here, but will fix issues where\n            // .5 gets interpreted as half of the total, instead of half of 1\n            // If it was supposed to be 128, this was already taken care of by `inputToRgb`\n            if (this._r < 1) { this._r = mathRound(this._r); }\n            if (this._g < 1) { this._g = mathRound(this._g); }\n            if (this._b < 1) { this._b = mathRound(this._b); }\n\n            this._ok = rgb.ok;\n            this._tc_id = tinyCounter++;\n        };\n\n        tinycolor.prototype = {\n            isDark: function() {\n                return this.getBrightness() < 128;\n            },\n            isLight: function() {\n                return !this.isDark();\n            },\n            isValid: function() {\n                return this._ok;\n            },\n            getOriginalInput: function() {\n                return this._originalInput;\n            },\n            getFormat: function() {\n                return this._format;\n            },\n            getAlpha: function() {\n                return this._a;\n            },\n            getBrightness: function() {\n                var rgb = this.toRgb();\n                return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;\n            },\n            setAlpha: function(value) {\n                this._a = boundAlpha(value);\n                this._roundA = mathRound(1000 * this._a) / 1000;\n                return this;\n            },\n            toHsv: function() {\n                var hsv = rgbToHsv(this._r, this._g, this._b);\n                return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };\n            },\n            toHsvString: function() {\n                var hsv = rgbToHsv(this._r, this._g, this._b);\n                var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);\n                return (this._a == 1) ?\n                    \"hsv(\"  + h + \", \" + s + \"%, \" + v + \"%)\" :\n                    \"hsva(\" + h + \", \" + s + \"%, \" + v + \"%, \"+ this._roundA + \")\";\n            },\n            toHsl: function() {\n                var hsl = rgbToHsl(this._r, this._g, this._b);\n                return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };\n            },\n            toHslString: function() {\n                var hsl = rgbToHsl(this._r, this._g, this._b);\n                var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);\n                return (this._a == 1) ?\n                    \"hsl(\"  + h + \", \" + s + \"%, \" + l + \"%)\" :\n                    \"hsla(\" + h + \", \" + s + \"%, \" + l + \"%, \"+ this._roundA + \")\";\n            },\n            toHex: function(allow3Char) {\n                return rgbToHex(this._r, this._g, this._b, allow3Char);\n            },\n            toHexString: function(allow3Char) {\n                return '#' + this.toHex(allow3Char);\n            },\n            toHex8: function() {\n                return rgbaToHex(this._r, this._g, this._b, this._a);\n            },\n            toHex8String: function() {\n                return '#' + this.toHex8();\n            },\n            toRgb: function() {\n                return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };\n            },\n            toRgbString: function() {\n                return (this._a == 1) ?\n                    \"rgb(\"  + mathRound(this._r) + \", \" + mathRound(this._g) + \", \" + mathRound(this._b) + \")\" :\n                    \"rgba(\" + mathRound(this._r) + \", \" + mathRound(this._g) + \", \" + mathRound(this._b) + \", \" + this._roundA + \")\";\n            },\n            toPercentageRgb: function() {\n                return { r: mathRound(bound01(this._r, 255) * 100) + \"%\", g: mathRound(bound01(this._g, 255) * 100) + \"%\", b: mathRound(bound01(this._b, 255) * 100) + \"%\", a: this._a };\n            },\n            toPercentageRgbString: function() {\n                return (this._a == 1) ?\n                    \"rgb(\"  + mathRound(bound01(this._r, 255) * 100) + \"%, \" + mathRound(bound01(this._g, 255) * 100) + \"%, \" + mathRound(bound01(this._b, 255) * 100) + \"%)\" :\n                    \"rgba(\" + mathRound(bound01(this._r, 255) * 100) + \"%, \" + mathRound(bound01(this._g, 255) * 100) + \"%, \" + mathRound(bound01(this._b, 255) * 100) + \"%, \" + this._roundA + \")\";\n            },\n            toName: function() {\n                if (this._a === 0) {\n                    return \"transparent\";\n                }\n\n                if (this._a < 1) {\n                    return false;\n                }\n\n                return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;\n            },\n            toFilter: function(secondColor) {\n                var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);\n                var secondHex8String = hex8String;\n                var gradientType = this._gradientType ? \"GradientType = 1, \" : \"\";\n\n                if (secondColor) {\n                    var s = tinycolor(secondColor);\n                    secondHex8String = s.toHex8String();\n                }\n\n                return \"progid:DXImageTransform.Microsoft.gradient(\"+gradientType+\"startColorstr=\"+hex8String+\",endColorstr=\"+secondHex8String+\")\";\n            },\n            toString: function(format) {\n                var formatSet = !!format;\n                format = format || this._format;\n\n                var formattedString = false;\n                var hasAlpha = this._a < 1 && this._a >= 0;\n                var needsAlphaFormat = !formatSet && hasAlpha && (format === \"hex\" || format === \"hex6\" || format === \"hex3\" || format === \"name\");\n\n                if (needsAlphaFormat) {\n                    // Special case for \"transparent\", all other non-alpha formats\n                    // will return rgba when there is transparency.\n                    if (format === \"name\" && this._a === 0) {\n                        return this.toName();\n                    }\n                    return this.toRgbString();\n                }\n                if (format === \"rgb\") {\n                    formattedString = this.toRgbString();\n                }\n                if (format === \"prgb\") {\n                    formattedString = this.toPercentageRgbString();\n                }\n                if (format === \"hex\" || format === \"hex6\") {\n                    formattedString = this.toHexString();\n                }\n                if (format === \"hex3\") {\n                    formattedString = this.toHexString(true);\n                }\n                if (format === \"hex8\") {\n                    formattedString = this.toHex8String();\n                }\n                if (format === \"name\") {\n                    formattedString = this.toName();\n                }\n                if (format === \"hsl\") {\n                    formattedString = this.toHslString();\n                }\n                if (format === \"hsv\") {\n                    formattedString = this.toHsvString();\n                }\n\n                return formattedString || this.toHexString();\n            },\n\n            _applyModification: function(fn, args) {\n                var color = fn.apply(null, [this].concat([].slice.call(args)));\n                this._r = color._r;\n                this._g = color._g;\n                this._b = color._b;\n                this.setAlpha(color._a);\n                return this;\n            },\n            lighten: function() {\n                return this._applyModification(lighten, arguments);\n            },\n            brighten: function() {\n                return this._applyModification(brighten, arguments);\n            },\n            darken: function() {\n                return this._applyModification(darken, arguments);\n            },\n            desaturate: function() {\n                return this._applyModification(desaturate, arguments);\n            },\n            saturate: function() {\n                return this._applyModification(saturate, arguments);\n            },\n            greyscale: function() {\n                return this._applyModification(greyscale, arguments);\n            },\n            spin: function() {\n                return this._applyModification(spin, arguments);\n            },\n\n            _applyCombination: function(fn, args) {\n                return fn.apply(null, [this].concat([].slice.call(args)));\n            },\n            analogous: function() {\n                return this._applyCombination(analogous, arguments);\n            },\n            complement: function() {\n                return this._applyCombination(complement, arguments);\n            },\n            monochromatic: function() {\n                return this._applyCombination(monochromatic, arguments);\n            },\n            splitcomplement: function() {\n                return this._applyCombination(splitcomplement, arguments);\n            },\n            triad: function() {\n                return this._applyCombination(triad, arguments);\n            },\n            tetrad: function() {\n                return this._applyCombination(tetrad, arguments);\n            }\n        };\n\n        // If input is an object, force 1 into \"1.0\" to handle ratios properly\n        // String input requires \"1.0\" as input, so 1 will be treated as 1\n        tinycolor.fromRatio = function(color, opts) {\n            if (typeof color == \"object\") {\n                var newColor = {};\n                for (var i in color) {\n                    if (color.hasOwnProperty(i)) {\n                        if (i === \"a\") {\n                            newColor[i] = color[i];\n                        }\n                        else {\n                            newColor[i] = convertToPercentage(color[i]);\n                        }\n                    }\n                }\n                color = newColor;\n            }\n\n            return tinycolor(color, opts);\n        };\n\n        // Given a string or object, convert that input to RGB\n        // Possible string inputs:\n        //\n        //     \"red\"\n        //     \"#f00\" or \"f00\"\n        //     \"#ff0000\" or \"ff0000\"\n        //     \"#ff000000\" or \"ff000000\"\n        //     \"rgb 255 0 0\" or \"rgb (255, 0, 0)\"\n        //     \"rgb 1.0 0 0\" or \"rgb (1, 0, 0)\"\n        //     \"rgba (255, 0, 0, 1)\" or \"rgba 255, 0, 0, 1\"\n        //     \"rgba (1.0, 0, 0, 1)\" or \"rgba 1.0, 0, 0, 1\"\n        //     \"hsl(0, 100%, 50%)\" or \"hsl 0 100% 50%\"\n        //     \"hsla(0, 100%, 50%, 1)\" or \"hsla 0 100% 50%, 1\"\n        //     \"hsv(0, 100%, 100%)\" or \"hsv 0 100% 100%\"\n        //\n        function inputToRGB(color) {\n\n            var rgb = { r: 0, g: 0, b: 0 };\n            var a = 1;\n            var ok = false;\n            var format = false;\n\n            if (typeof color == \"string\") {\n                color = stringInputToObject(color);\n            }\n\n            if (typeof color == \"object\") {\n                if (color.hasOwnProperty(\"r\") && color.hasOwnProperty(\"g\") && color.hasOwnProperty(\"b\")) {\n                    rgb = rgbToRgb(color.r, color.g, color.b);\n                    ok = true;\n                    format = String(color.r).substr(-1) === \"%\" ? \"prgb\" : \"rgb\";\n                }\n                else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"v\")) {\n                    color.s = convertToPercentage(color.s);\n                    color.v = convertToPercentage(color.v);\n                    rgb = hsvToRgb(color.h, color.s, color.v);\n                    ok = true;\n                    format = \"hsv\";\n                }\n                else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"l\")) {\n                    color.s = convertToPercentage(color.s);\n                    color.l = convertToPercentage(color.l);\n                    rgb = hslToRgb(color.h, color.s, color.l);\n                    ok = true;\n                    format = \"hsl\";\n                }\n\n                if (color.hasOwnProperty(\"a\")) {\n                    a = color.a;\n                }\n            }\n\n            a = boundAlpha(a);\n\n            return {\n                ok: ok,\n                format: color.format || format,\n                r: mathMin(255, mathMax(rgb.r, 0)),\n                g: mathMin(255, mathMax(rgb.g, 0)),\n                b: mathMin(255, mathMax(rgb.b, 0)),\n                a: a\n            };\n        }\n\n\n        // Conversion Functions\n        // --------------------\n\n        // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\n        // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>\n\n        // `rgbToRgb`\n        // Handle bounds / percentage checking to conform to CSS color spec\n        // <http://www.w3.org/TR/css3-color/>\n        // *Assumes:* r, g, b in [0, 255] or [0, 1]\n        // *Returns:* { r, g, b } in [0, 255]\n        function rgbToRgb(r, g, b){\n            return {\n                r: bound01(r, 255) * 255,\n                g: bound01(g, 255) * 255,\n                b: bound01(b, 255) * 255\n            };\n        }\n\n        // `rgbToHsl`\n        // Converts an RGB color value to HSL.\n        // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n        // *Returns:* { h, s, l } in [0,1]\n        function rgbToHsl(r, g, b) {\n\n            r = bound01(r, 255);\n            g = bound01(g, 255);\n            b = bound01(b, 255);\n\n            var max = mathMax(r, g, b), min = mathMin(r, g, b);\n            var h, s, l = (max + min) / 2;\n\n            if(max == min) {\n                h = s = 0; // achromatic\n            }\n            else {\n                var d = max - min;\n                s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n                switch(max) {\n                    case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                    case g: h = (b - r) / d + 2; break;\n                    case b: h = (r - g) / d + 4; break;\n                }\n\n                h /= 6;\n            }\n\n            return { h: h, s: s, l: l };\n        }\n\n        // `hslToRgb`\n        // Converts an HSL color value to RGB.\n        // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n        // *Returns:* { r, g, b } in the set [0, 255]\n        function hslToRgb(h, s, l) {\n            var r, g, b;\n\n            h = bound01(h, 360);\n            s = bound01(s, 100);\n            l = bound01(l, 100);\n\n            function hue2rgb(p, q, t) {\n                if(t < 0) t += 1;\n                if(t > 1) t -= 1;\n                if(t < 1/6) return p + (q - p) * 6 * t;\n                if(t < 1/2) return q;\n                if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n                return p;\n            }\n\n            if(s === 0) {\n                r = g = b = l; // achromatic\n            }\n            else {\n                var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n                var 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 { r: r * 255, g: g * 255, b: b * 255 };\n        }\n\n        // `rgbToHsv`\n        // Converts an RGB color value to HSV\n        // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]\n        // *Returns:* { h, s, v } in [0,1]\n        function rgbToHsv(r, g, b) {\n\n            r = bound01(r, 255);\n            g = bound01(g, 255);\n            b = bound01(b, 255);\n\n            var max = mathMax(r, g, b), min = mathMin(r, g, b);\n            var h, s, v = max;\n\n            var d = max - min;\n            s = max === 0 ? 0 : d / max;\n\n            if(max == min) {\n                h = 0; // achromatic\n            }\n            else {\n                switch(max) {\n                    case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                    case g: h = (b - r) / d + 2; break;\n                    case b: h = (r - g) / d + 4; break;\n                }\n                h /= 6;\n            }\n            return { h: h, s: s, v: v };\n        }\n\n        // `hsvToRgb`\n        // Converts an HSV color value to RGB.\n        // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]\n        // *Returns:* { r, g, b } in the set [0, 255]\n        function hsvToRgb(h, s, v) {\n\n            h = bound01(h, 360) * 6;\n            s = bound01(s, 100);\n            v = bound01(v, 100);\n\n            var i = math.floor(h),\n                f = h - i,\n                p = v * (1 - s),\n                q = v * (1 - f * s),\n                t = v * (1 - (1 - f) * s),\n                mod = i % 6,\n                r = [v, q, p, p, t, v][mod],\n                g = [t, v, v, q, p, p][mod],\n                b = [p, p, t, v, v, q][mod];\n\n            return { r: r * 255, g: g * 255, b: b * 255 };\n        }\n\n        // `rgbToHex`\n        // Converts an RGB color to hex\n        // Assumes r, g, and b are contained in the set [0, 255]\n        // Returns a 3 or 6 character hex\n        function rgbToHex(r, g, b, allow3Char) {\n\n            var hex = [\n                pad2(mathRound(r).toString(16)),\n                pad2(mathRound(g).toString(16)),\n                pad2(mathRound(b).toString(16))\n            ];\n\n            // Return a 3 character hex if possible\n            if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {\n                return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);\n            }\n\n            return hex.join(\"\");\n        }\n        // `rgbaToHex`\n        // Converts an RGBA color plus alpha transparency to hex\n        // Assumes r, g, b and a are contained in the set [0, 255]\n        // Returns an 8 character hex\n        function rgbaToHex(r, g, b, a) {\n\n            var hex = [\n                pad2(convertDecimalToHex(a)),\n                pad2(mathRound(r).toString(16)),\n                pad2(mathRound(g).toString(16)),\n                pad2(mathRound(b).toString(16))\n            ];\n\n            return hex.join(\"\");\n        }\n\n        // `equals`\n        // Can be called with any tinycolor input\n        tinycolor.equals = function (color1, color2) {\n            if (!color1 || !color2) { return false; }\n            return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();\n        };\n        tinycolor.random = function() {\n            return tinycolor.fromRatio({\n                r: mathRandom(),\n                g: mathRandom(),\n                b: mathRandom()\n            });\n        };\n\n\n        // Modification Functions\n        // ----------------------\n        // Thanks to less.js for some of the basics here\n        // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>\n\n        function desaturate(color, amount) {\n            amount = (amount === 0) ? 0 : (amount || 10);\n            var hsl = tinycolor(color).toHsl();\n            hsl.s -= amount / 100;\n            hsl.s = clamp01(hsl.s);\n            return tinycolor(hsl);\n        }\n\n        function saturate(color, amount) {\n            amount = (amount === 0) ? 0 : (amount || 10);\n            var hsl = tinycolor(color).toHsl();\n            hsl.s += amount / 100;\n            hsl.s = clamp01(hsl.s);\n            return tinycolor(hsl);\n        }\n\n        function greyscale(color) {\n            return tinycolor(color).desaturate(100);\n        }\n\n        function lighten (color, amount) {\n            amount = (amount === 0) ? 0 : (amount || 10);\n            var hsl = tinycolor(color).toHsl();\n            hsl.l += amount / 100;\n            hsl.l = clamp01(hsl.l);\n            return tinycolor(hsl);\n        }\n\n        function brighten(color, amount) {\n            amount = (amount === 0) ? 0 : (amount || 10);\n            var rgb = 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 tinycolor(rgb);\n        }\n\n        function darken (color, amount) {\n            amount = (amount === 0) ? 0 : (amount || 10);\n            var hsl = tinycolor(color).toHsl();\n            hsl.l -= amount / 100;\n            hsl.l = clamp01(hsl.l);\n            return tinycolor(hsl);\n        }\n\n        // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.\n        // Values outside of this range will be wrapped into this range.\n        function spin(color, amount) {\n            var hsl = tinycolor(color).toHsl();\n            var hue = (mathRound(hsl.h) + amount) % 360;\n            hsl.h = hue < 0 ? 360 + hue : hue;\n            return tinycolor(hsl);\n        }\n\n        // Combination Functions\n        // ---------------------\n        // Thanks to jQuery xColor for some of the ideas behind these\n        // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>\n\n        function complement(color) {\n            var hsl = tinycolor(color).toHsl();\n            hsl.h = (hsl.h + 180) % 360;\n            return tinycolor(hsl);\n        }\n\n        function triad(color) {\n            var hsl = tinycolor(color).toHsl();\n            var h = hsl.h;\n            return [\n                tinycolor(color),\n                tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),\n                tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })\n            ];\n        }\n\n        function tetrad(color) {\n            var hsl = tinycolor(color).toHsl();\n            var h = hsl.h;\n            return [\n                tinycolor(color),\n                tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),\n                tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),\n                tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })\n            ];\n        }\n\n        function splitcomplement(color) {\n            var hsl = tinycolor(color).toHsl();\n            var h = hsl.h;\n            return [\n                tinycolor(color),\n                tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),\n                tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})\n            ];\n        }\n\n        function analogous(color, results, slices) {\n            results = results || 6;\n            slices = slices || 30;\n\n            var hsl = tinycolor(color).toHsl();\n            var part = 360 / slices;\n            var ret = [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(tinycolor(hsl));\n            }\n            return ret;\n        }\n\n        function monochromatic(color, results) {\n            results = results || 6;\n            var hsv = tinycolor(color).toHsv();\n            var h = hsv.h, s = hsv.s, v = hsv.v;\n            var ret = [];\n            var modification = 1 / results;\n\n            while (results--) {\n                ret.push(tinycolor({ h: h, s: s, v: v}));\n                v = (v + modification) % 1;\n            }\n\n            return ret;\n        }\n\n        // Utility Functions\n        // ---------------------\n\n        tinycolor.mix = function(color1, color2, amount) {\n            amount = (amount === 0) ? 0 : (amount || 50);\n\n            var rgb1 = tinycolor(color1).toRgb();\n            var rgb2 = tinycolor(color2).toRgb();\n\n            var p = amount / 100;\n            var w = p * 2 - 1;\n            var a = rgb2.a - rgb1.a;\n\n            var w1;\n\n            if (w * a == -1) {\n                w1 = w;\n            } else {\n                w1 = (w + a) / (1 + w * a);\n            }\n\n            w1 = (w1 + 1) / 2;\n\n            var w2 = 1 - w1;\n\n            var rgba = {\n                r: rgb2.r * w1 + rgb1.r * w2,\n                g: rgb2.g * w1 + rgb1.g * w2,\n                b: rgb2.b * w1 + rgb1.b * w2,\n                a: rgb2.a * p  + rgb1.a * (1 - p)\n            };\n\n            return tinycolor(rgba);\n        };\n\n\n        // Readability Functions\n        // ---------------------\n        // <http://www.w3.org/TR/AERT#color-contrast>\n\n        // `readability`\n        // Analyze the 2 colors and returns an object with the following properties:\n        //    `brightness`: difference in brightness between the two colors\n        //    `color`: difference in color/hue between the two colors\n        tinycolor.readability = function(color1, color2) {\n            var c1 = tinycolor(color1);\n            var c2 = tinycolor(color2);\n            var rgb1 = c1.toRgb();\n            var rgb2 = c2.toRgb();\n            var brightnessA = c1.getBrightness();\n            var brightnessB = c2.getBrightness();\n            var colorDiff = (\n                Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +\n                Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +\n                Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)\n            );\n\n            return {\n                brightness: Math.abs(brightnessA - brightnessB),\n                color: colorDiff\n            };\n        };\n\n        // `readable`\n        // http://www.w3.org/TR/AERT#color-contrast\n        // Ensure that foreground and background color combinations provide sufficient contrast.\n        // *Example*\n        //    tinycolor.isReadable(\"#000\", \"#111\") => false\n        tinycolor.isReadable = function(color1, color2) {\n            var readability = tinycolor.readability(color1, color2);\n            return readability.brightness > 125 && readability.color > 500;\n        };\n\n        // `mostReadable`\n        // Given a base color and a list of possible foreground or background\n        // colors for that base, returns the most readable color.\n        // *Example*\n        //    tinycolor.mostReadable(\"#123\", [\"#fff\", \"#000\"]) => \"#000\"\n        tinycolor.mostReadable = function(baseColor, colorList) {\n            var bestColor = null;\n            var bestScore = 0;\n            var bestIsReadable = false;\n            for (var i=0; i < colorList.length; i++) {\n\n                // We normalize both around the \"acceptable\" breaking point,\n                // but rank brightness constrast higher than hue.\n\n                var readability = tinycolor.readability(baseColor, colorList[i]);\n                var readable = readability.brightness > 125 && readability.color > 500;\n                var score = 3 * (readability.brightness / 125) + (readability.color / 500);\n\n                if ((readable && ! bestIsReadable) ||\n                    (readable && bestIsReadable && score > bestScore) ||\n                    ((! readable) && (! bestIsReadable) && score > bestScore)) {\n                    bestIsReadable = readable;\n                    bestScore = score;\n                    bestColor = tinycolor(colorList[i]);\n                }\n            }\n            return bestColor;\n        };\n\n\n        // Big List of Colors\n        // ------------------\n        // <http://www.w3.org/TR/css3-color/#svg-color>\n        var names = tinycolor.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: \"663399\",\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        };\n\n        // Make it easy to access colors via `hexNames[hex]`\n        var hexNames = tinycolor.hexNames = flip(names);\n\n\n        // Utilities\n        // ---------\n\n        // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`\n        function flip(o) {\n            var flipped = { };\n            for (var i in o) {\n                if (o.hasOwnProperty(i)) {\n                    flipped[o[i]] = i;\n                }\n            }\n            return flipped;\n        }\n\n        // Return a valid alpha value [0,1] with all invalid values being set to 1\n        function boundAlpha(a) {\n            a = parseFloat(a);\n\n            if (isNaN(a) || a < 0 || a > 1) {\n                a = 1;\n            }\n\n            return a;\n        }\n\n        // Take input from [0, n] and return it as [0, 1]\n        function bound01(n, max) {\n            if (isOnePointZero(n)) { n = \"100%\"; }\n\n            var processPercent = isPercentage(n);\n            n = mathMin(max, mathMax(0, parseFloat(n)));\n\n            // Automatically convert percentage into number\n            if (processPercent) {\n                n = parseInt(n * max, 10) / 100;\n            }\n\n            // Handle floating point rounding errors\n            if ((math.abs(n - max) < 0.000001)) {\n                return 1;\n            }\n\n            // Convert into [0, 1] range if it isn't already\n            return (n % max) / parseFloat(max);\n        }\n\n        // Force a number between 0 and 1\n        function clamp01(val) {\n            return mathMin(1, mathMax(0, val));\n        }\n\n        // Parse a base-16 hex value into a base-10 integer\n        function parseIntFromHex(val) {\n            return parseInt(val, 16);\n        }\n\n        // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\n        // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>\n        function isOnePointZero(n) {\n            return typeof n == \"string\" && n.indexOf('.') != -1 && parseFloat(n) === 1;\n        }\n\n        // Check to see if string passed in is a percentage\n        function isPercentage(n) {\n            return typeof n === \"string\" && n.indexOf('%') != -1;\n        }\n\n        // Force a hex value to have 2 characters\n        function pad2(c) {\n            return c.length == 1 ? '0' + c : '' + c;\n        }\n\n        // Replace a decimal with it's percentage value\n        function convertToPercentage(n) {\n            if (n <= 1) {\n                n = (n * 100) + \"%\";\n            }\n\n            return n;\n        }\n\n        // Converts a decimal to a hex value\n        function convertDecimalToHex(d) {\n            return Math.round(parseFloat(d) * 255).toString(16);\n        }\n        // Converts a hex value to a decimal\n        function convertHexToDecimal(h) {\n            return (parseIntFromHex(h) / 255);\n        }\n\n        var matchers = (function() {\n\n            // <http://www.w3.org/TR/css3-values/#integers>\n            var CSS_INTEGER = \"[-\\\\+]?\\\\d+%?\";\n\n            // <http://www.w3.org/TR/css3-values/#number-value>\n            var CSS_NUMBER = \"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\";\n\n            // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.\n            var CSS_UNIT = \"(?:\" + CSS_NUMBER + \")|(?:\" + CSS_INTEGER + \")\";\n\n            // Actual matching.\n            // Parentheses and commas are optional, but not required.\n            // Whitespace can take the place of commas or opening paren\n            var PERMISSIVE_MATCH3 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n            var PERMISSIVE_MATCH4 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n\n            return {\n                rgb: new RegExp(\"rgb\" + PERMISSIVE_MATCH3),\n                rgba: new RegExp(\"rgba\" + PERMISSIVE_MATCH4),\n                hsl: new RegExp(\"hsl\" + PERMISSIVE_MATCH3),\n                hsla: new RegExp(\"hsla\" + PERMISSIVE_MATCH4),\n                hsv: new RegExp(\"hsv\" + PERMISSIVE_MATCH3),\n                hsva: new RegExp(\"hsva\" + PERMISSIVE_MATCH4),\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                hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n            };\n        })();\n\n        // `stringInputToObject`\n        // Permissive string parsing.  Take in a number of formats, and output an object\n        // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`\n        function stringInputToObject(color) {\n\n            color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();\n            var named = false;\n            if (names[color]) {\n                color = names[color];\n                named = true;\n            }\n            else if (color == 'transparent') {\n                return { r: 0, g: 0, b: 0, a: 0, format: \"name\" };\n            }\n\n            // Try to match string input using regular expressions.\n            // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]\n            // Just return an object and let the conversion functions handle that.\n            // This way the result will be the same whether the tinycolor is initialized with string or object.\n            var match;\n            if ((match = matchers.rgb.exec(color))) {\n                return { r: match[1], g: match[2], b: match[3] };\n            }\n            if ((match = matchers.rgba.exec(color))) {\n                return { r: match[1], g: match[2], b: match[3], a: match[4] };\n            }\n            if ((match = matchers.hsl.exec(color))) {\n                return { h: match[1], s: match[2], l: match[3] };\n            }\n            if ((match = matchers.hsla.exec(color))) {\n                return { h: match[1], s: match[2], l: match[3], a: match[4] };\n            }\n            if ((match = matchers.hsv.exec(color))) {\n                return { h: match[1], s: match[2], v: match[3] };\n            }\n            if ((match = matchers.hsva.exec(color))) {\n                return { h: match[1], s: match[2], v: match[3], a: match[4] };\n            }\n            if ((match = matchers.hex8.exec(color))) {\n                return {\n                    a: convertHexToDecimal(match[1]),\n                    r: parseIntFromHex(match[2]),\n                    g: parseIntFromHex(match[3]),\n                    b: parseIntFromHex(match[4]),\n                    format: named ? \"name\" : \"hex8\"\n                };\n            }\n            if ((match = matchers.hex6.exec(color))) {\n                return {\n                    r: parseIntFromHex(match[1]),\n                    g: parseIntFromHex(match[2]),\n                    b: parseIntFromHex(match[3]),\n                    format: named ? \"name\" : \"hex\"\n                };\n            }\n            if ((match = matchers.hex3.exec(color))) {\n                return {\n                    r: parseIntFromHex(match[1] + '' + match[1]),\n                    g: parseIntFromHex(match[2] + '' + match[2]),\n                    b: parseIntFromHex(match[3] + '' + match[3]),\n                    format: named ? \"name\" : \"hex\"\n                };\n            }\n\n            return false;\n        }\n\n        window.tinycolor = tinycolor;\n    })();\n\n    $(function () {\n        if ($.fn.spectrum.load) {\n            $.fn.spectrum.processNativeColorInputs();\n        }\n    });\n\n});\n","jquery/spectrum/tinycolor.js":"// This file is autogenerated. v1.6.0\n// It's here at this path for backwards compatibility for links to it\n// but the npm package now exports both CJS and ESM.\n// See https://github.com/bgrins/TinyColor/ for instructions.\n(function (global, factory) {\n    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n        typeof define === 'function' && define.amd ? define(factory) :\n            (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.tinycolor = factory());\n})(this, (function () { 'use strict';\n\n    function _typeof(obj) {\n        \"@babel/helpers - typeof\";\n\n        return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) {\n            return typeof obj;\n        } : function (obj) {\n            return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n        }, _typeof(obj);\n    }\n\n    // https://github.com/bgrins/TinyColor\n    // Brian Grinstead, MIT License\n\n    var trimLeft = /^\\s+/;\n    var trimRight = /\\s+$/;\n    function tinycolor(color, opts) {\n        color = color ? color : \"\";\n        opts = opts || {};\n\n        // If input is already a tinycolor, return itself\n        if (color instanceof tinycolor) {\n            return color;\n        }\n        // If we are called as a function, call using new instead\n        if (!(this instanceof tinycolor)) {\n            return new tinycolor(color, opts);\n        }\n        var rgb = inputToRGB(color);\n        this._originalInput = color, this._r = rgb.r, this._g = rgb.g, this._b = rgb.b, this._a = rgb.a, this._roundA = Math.round(100 * this._a) / 100, this._format = opts.format || rgb.format;\n        this._gradientType = opts.gradientType;\n\n        // Don't let the range of [0,255] come back in [0,1].\n        // Potentially lose a little bit of precision here, but will fix issues where\n        // .5 gets interpreted as half of the total, instead of half of 1\n        // If it was supposed to be 128, this was already taken care of by `inputToRgb`\n        if (this._r < 1) this._r = Math.round(this._r);\n        if (this._g < 1) this._g = Math.round(this._g);\n        if (this._b < 1) this._b = Math.round(this._b);\n        this._ok = rgb.ok;\n    }\n    tinycolor.prototype = {\n        isDark: function isDark() {\n            return this.getBrightness() < 128;\n        },\n        isLight: function isLight() {\n            return !this.isDark();\n        },\n        isValid: function isValid() {\n            return this._ok;\n        },\n        getOriginalInput: function getOriginalInput() {\n            return this._originalInput;\n        },\n        getFormat: function getFormat() {\n            return this._format;\n        },\n        getAlpha: function getAlpha() {\n            return this._a;\n        },\n        getBrightness: function getBrightness() {\n            //http://www.w3.org/TR/AERT#color-contrast\n            var rgb = this.toRgb();\n            return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;\n        },\n        getLuminance: function getLuminance() {\n            //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef\n            var rgb = this.toRgb();\n            var RsRGB, GsRGB, BsRGB, R, G, B;\n            RsRGB = rgb.r / 255;\n            GsRGB = rgb.g / 255;\n            BsRGB = rgb.b / 255;\n            if (RsRGB <= 0.03928) R = RsRGB / 12.92;else R = Math.pow((RsRGB + 0.055) / 1.055, 2.4);\n            if (GsRGB <= 0.03928) G = GsRGB / 12.92;else G = Math.pow((GsRGB + 0.055) / 1.055, 2.4);\n            if (BsRGB <= 0.03928) B = BsRGB / 12.92;else B = Math.pow((BsRGB + 0.055) / 1.055, 2.4);\n            return 0.2126 * R + 0.7152 * G + 0.0722 * B;\n        },\n        setAlpha: function setAlpha(value) {\n            this._a = boundAlpha(value);\n            this._roundA = Math.round(100 * this._a) / 100;\n            return this;\n        },\n        toHsv: function toHsv() {\n            var hsv = rgbToHsv(this._r, this._g, this._b);\n            return {\n                h: hsv.h * 360,\n                s: hsv.s,\n                v: hsv.v,\n                a: this._a\n            };\n        },\n        toHsvString: function toHsvString() {\n            var hsv = rgbToHsv(this._r, this._g, this._b);\n            var h = Math.round(hsv.h * 360),\n                s = Math.round(hsv.s * 100),\n                v = Math.round(hsv.v * 100);\n            return this._a == 1 ? \"hsv(\" + h + \", \" + s + \"%, \" + v + \"%)\" : \"hsva(\" + h + \", \" + s + \"%, \" + v + \"%, \" + this._roundA + \")\";\n        },\n        toHsl: function toHsl() {\n            var hsl = rgbToHsl(this._r, this._g, this._b);\n            return {\n                h: hsl.h * 360,\n                s: hsl.s,\n                l: hsl.l,\n                a: this._a\n            };\n        },\n        toHslString: function toHslString() {\n            var hsl = rgbToHsl(this._r, this._g, this._b);\n            var h = Math.round(hsl.h * 360),\n                s = Math.round(hsl.s * 100),\n                l = Math.round(hsl.l * 100);\n            return this._a == 1 ? \"hsl(\" + h + \", \" + s + \"%, \" + l + \"%)\" : \"hsla(\" + h + \", \" + s + \"%, \" + l + \"%, \" + this._roundA + \")\";\n        },\n        toHex: function toHex(allow3Char) {\n            return rgbToHex(this._r, this._g, this._b, allow3Char);\n        },\n        toHexString: function toHexString(allow3Char) {\n            return \"#\" + this.toHex(allow3Char);\n        },\n        toHex8: function toHex8(allow4Char) {\n            return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);\n        },\n        toHex8String: function toHex8String(allow4Char) {\n            return \"#\" + this.toHex8(allow4Char);\n        },\n        toRgb: function toRgb() {\n            return {\n                r: Math.round(this._r),\n                g: Math.round(this._g),\n                b: Math.round(this._b),\n                a: this._a\n            };\n        },\n        toRgbString: function toRgbString() {\n            return this._a == 1 ? \"rgb(\" + Math.round(this._r) + \", \" + Math.round(this._g) + \", \" + Math.round(this._b) + \")\" : \"rgba(\" + Math.round(this._r) + \", \" + Math.round(this._g) + \", \" + Math.round(this._b) + \", \" + this._roundA + \")\";\n        },\n        toPercentageRgb: function toPercentageRgb() {\n            return {\n                r: Math.round(bound01(this._r, 255) * 100) + \"%\",\n                g: Math.round(bound01(this._g, 255) * 100) + \"%\",\n                b: Math.round(bound01(this._b, 255) * 100) + \"%\",\n                a: this._a\n            };\n        },\n        toPercentageRgbString: function toPercentageRgbString() {\n            return this._a == 1 ? \"rgb(\" + Math.round(bound01(this._r, 255) * 100) + \"%, \" + Math.round(bound01(this._g, 255) * 100) + \"%, \" + Math.round(bound01(this._b, 255) * 100) + \"%)\" : \"rgba(\" + Math.round(bound01(this._r, 255) * 100) + \"%, \" + Math.round(bound01(this._g, 255) * 100) + \"%, \" + Math.round(bound01(this._b, 255) * 100) + \"%, \" + this._roundA + \")\";\n        },\n        toName: function toName() {\n            if (this._a === 0) {\n                return \"transparent\";\n            }\n            if (this._a < 1) {\n                return false;\n            }\n            return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;\n        },\n        toFilter: function toFilter(secondColor) {\n            var hex8String = \"#\" + rgbaToArgbHex(this._r, this._g, this._b, this._a);\n            var secondHex8String = hex8String;\n            var gradientType = this._gradientType ? \"GradientType = 1, \" : \"\";\n            if (secondColor) {\n                var s = tinycolor(secondColor);\n                secondHex8String = \"#\" + rgbaToArgbHex(s._r, s._g, s._b, s._a);\n            }\n            return \"progid:DXImageTransform.Microsoft.gradient(\" + gradientType + \"startColorstr=\" + hex8String + \",endColorstr=\" + secondHex8String + \")\";\n        },\n        toString: function toString(format) {\n            var formatSet = !!format;\n            format = format || this._format;\n            var formattedString = false;\n            var hasAlpha = this._a < 1 && this._a >= 0;\n            var needsAlphaFormat = !formatSet && hasAlpha && (format === \"hex\" || format === \"hex6\" || format === \"hex3\" || format === \"hex4\" || format === \"hex8\" || format === \"name\");\n            if (needsAlphaFormat) {\n                // Special case for \"transparent\", all other non-alpha formats\n                // will return rgba when there is transparency.\n                if (format === \"name\" && this._a === 0) {\n                    return this.toName();\n                }\n                return this.toRgbString();\n            }\n            if (format === \"rgb\") {\n                formattedString = this.toRgbString();\n            }\n            if (format === \"prgb\") {\n                formattedString = this.toPercentageRgbString();\n            }\n            if (format === \"hex\" || format === \"hex6\") {\n                formattedString = this.toHexString();\n            }\n            if (format === \"hex3\") {\n                formattedString = this.toHexString(true);\n            }\n            if (format === \"hex4\") {\n                formattedString = this.toHex8String(true);\n            }\n            if (format === \"hex8\") {\n                formattedString = this.toHex8String();\n            }\n            if (format === \"name\") {\n                formattedString = this.toName();\n            }\n            if (format === \"hsl\") {\n                formattedString = this.toHslString();\n            }\n            if (format === \"hsv\") {\n                formattedString = this.toHsvString();\n            }\n            return formattedString || this.toHexString();\n        },\n        clone: function clone() {\n            return tinycolor(this.toString());\n        },\n        _applyModification: function _applyModification(fn, args) {\n            var color = fn.apply(null, [this].concat([].slice.call(args)));\n            this._r = color._r;\n            this._g = color._g;\n            this._b = color._b;\n            this.setAlpha(color._a);\n            return this;\n        },\n        lighten: function lighten() {\n            return this._applyModification(_lighten, arguments);\n        },\n        brighten: function brighten() {\n            return this._applyModification(_brighten, arguments);\n        },\n        darken: function darken() {\n            return this._applyModification(_darken, arguments);\n        },\n        desaturate: function desaturate() {\n            return this._applyModification(_desaturate, arguments);\n        },\n        saturate: function saturate() {\n            return this._applyModification(_saturate, arguments);\n        },\n        greyscale: function greyscale() {\n            return this._applyModification(_greyscale, arguments);\n        },\n        spin: function spin() {\n            return this._applyModification(_spin, arguments);\n        },\n        _applyCombination: function _applyCombination(fn, args) {\n            return fn.apply(null, [this].concat([].slice.call(args)));\n        },\n        analogous: function analogous() {\n            return this._applyCombination(_analogous, arguments);\n        },\n        complement: function complement() {\n            return this._applyCombination(_complement, arguments);\n        },\n        monochromatic: function monochromatic() {\n            return this._applyCombination(_monochromatic, arguments);\n        },\n        splitcomplement: function splitcomplement() {\n            return this._applyCombination(_splitcomplement, arguments);\n        },\n        // Disabled until https://github.com/bgrins/TinyColor/issues/254\n        // polyad: function (number) {\n        //   return this._applyCombination(polyad, [number]);\n        // },\n        triad: function triad() {\n            return this._applyCombination(polyad, [3]);\n        },\n        tetrad: function tetrad() {\n            return this._applyCombination(polyad, [4]);\n        }\n    };\n\n    // If input is an object, force 1 into \"1.0\" to handle ratios properly\n    // String input requires \"1.0\" as input, so 1 will be treated as 1\n    tinycolor.fromRatio = function (color, opts) {\n        if (_typeof(color) == \"object\") {\n            var newColor = {};\n            for (var i in color) {\n                if (color.hasOwnProperty(i)) {\n                    if (i === \"a\") {\n                        newColor[i] = color[i];\n                    } else {\n                        newColor[i] = convertToPercentage(color[i]);\n                    }\n                }\n            }\n            color = newColor;\n        }\n        return tinycolor(color, opts);\n    };\n\n    // Given a string or object, convert that input to RGB\n    // Possible string inputs:\n    //\n    //     \"red\"\n    //     \"#f00\" or \"f00\"\n    //     \"#ff0000\" or \"ff0000\"\n    //     \"#ff000000\" or \"ff000000\"\n    //     \"rgb 255 0 0\" or \"rgb (255, 0, 0)\"\n    //     \"rgb 1.0 0 0\" or \"rgb (1, 0, 0)\"\n    //     \"rgba (255, 0, 0, 1)\" or \"rgba 255, 0, 0, 1\"\n    //     \"rgba (1.0, 0, 0, 1)\" or \"rgba 1.0, 0, 0, 1\"\n    //     \"hsl(0, 100%, 50%)\" or \"hsl 0 100% 50%\"\n    //     \"hsla(0, 100%, 50%, 1)\" or \"hsla 0 100% 50%, 1\"\n    //     \"hsv(0, 100%, 100%)\" or \"hsv 0 100% 100%\"\n    //\n    function inputToRGB(color) {\n        var rgb = {\n            r: 0,\n            g: 0,\n            b: 0\n        };\n        var a = 1;\n        var s = null;\n        var v = null;\n        var l = null;\n        var ok = false;\n        var format = false;\n        if (typeof color == \"string\") {\n            color = stringInputToObject(color);\n        }\n        if (_typeof(color) == \"object\") {\n            if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {\n                rgb = rgbToRgb(color.r, color.g, color.b);\n                ok = true;\n                format = String(color.r).substr(-1) === \"%\" ? \"prgb\" : \"rgb\";\n            } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {\n                s = convertToPercentage(color.s);\n                v = convertToPercentage(color.v);\n                rgb = hsvToRgb(color.h, s, v);\n                ok = true;\n                format = \"hsv\";\n            } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {\n                s = convertToPercentage(color.s);\n                l = convertToPercentage(color.l);\n                rgb = hslToRgb(color.h, s, l);\n                ok = true;\n                format = \"hsl\";\n            }\n            if (color.hasOwnProperty(\"a\")) {\n                a = color.a;\n            }\n        }\n        a = boundAlpha(a);\n        return {\n            ok: ok,\n            format: color.format || format,\n            r: Math.min(255, Math.max(rgb.r, 0)),\n            g: Math.min(255, Math.max(rgb.g, 0)),\n            b: Math.min(255, Math.max(rgb.b, 0)),\n            a: a\n        };\n    }\n\n    // Conversion Functions\n    // --------------------\n\n    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\n    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>\n\n    // `rgbToRgb`\n    // Handle bounds / percentage checking to conform to CSS color spec\n    // <http://www.w3.org/TR/css3-color/>\n    // *Assumes:* r, g, b in [0, 255] or [0, 1]\n    // *Returns:* { r, g, b } in [0, 255]\n    function rgbToRgb(r, g, b) {\n        return {\n            r: bound01(r, 255) * 255,\n            g: bound01(g, 255) * 255,\n            b: bound01(b, 255) * 255\n        };\n    }\n\n    // `rgbToHsl`\n    // Converts an RGB color value to HSL.\n    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n    // *Returns:* { h, s, l } in [0,1]\n    function rgbToHsl(r, g, b) {\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n        var max = Math.max(r, g, b),\n            min = Math.min(r, g, b);\n        var h,\n            s,\n            l = (max + min) / 2;\n        if (max == min) {\n            h = s = 0; // achromatic\n        } else {\n            var d = max - min;\n            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n            switch (max) {\n                case r:\n                    h = (g - b) / d + (g < b ? 6 : 0);\n                    break;\n                case g:\n                    h = (b - r) / d + 2;\n                    break;\n                case b:\n                    h = (r - g) / d + 4;\n                    break;\n            }\n            h /= 6;\n        }\n        return {\n            h: h,\n            s: s,\n            l: l\n        };\n    }\n\n    // `hslToRgb`\n    // Converts an HSL color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n    function hslToRgb(h, s, l) {\n        var r, g, b;\n        h = bound01(h, 360);\n        s = bound01(s, 100);\n        l = bound01(l, 100);\n        function hue2rgb(p, q, t) {\n            if (t < 0) t += 1;\n            if (t > 1) t -= 1;\n            if (t < 1 / 6) return p + (q - p) * 6 * t;\n            if (t < 1 / 2) return q;\n            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n            return p;\n        }\n        if (s === 0) {\n            r = g = b = l; // achromatic\n        } else {\n            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n            var 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        return {\n            r: r * 255,\n            g: g * 255,\n            b: b * 255\n        };\n    }\n\n    // `rgbToHsv`\n    // Converts an RGB color value to HSV\n    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]\n    // *Returns:* { h, s, v } in [0,1]\n    function rgbToHsv(r, g, b) {\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n        var max = Math.max(r, g, b),\n            min = Math.min(r, g, b);\n        var h,\n            s,\n            v = max;\n        var d = max - min;\n        s = max === 0 ? 0 : d / max;\n        if (max == min) {\n            h = 0; // achromatic\n        } else {\n            switch (max) {\n                case r:\n                    h = (g - b) / d + (g < b ? 6 : 0);\n                    break;\n                case g:\n                    h = (b - r) / d + 2;\n                    break;\n                case b:\n                    h = (r - g) / d + 4;\n                    break;\n            }\n            h /= 6;\n        }\n        return {\n            h: h,\n            s: s,\n            v: v\n        };\n    }\n\n    // `hsvToRgb`\n    // Converts an HSV color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n    function hsvToRgb(h, s, v) {\n        h = bound01(h, 360) * 6;\n        s = bound01(s, 100);\n        v = bound01(v, 100);\n        var i = Math.floor(h),\n            f = h - i,\n            p = v * (1 - s),\n            q = v * (1 - f * s),\n            t = v * (1 - (1 - f) * s),\n            mod = i % 6,\n            r = [v, q, p, p, t, v][mod],\n            g = [t, v, v, q, p, p][mod],\n            b = [p, p, t, v, v, q][mod];\n        return {\n            r: r * 255,\n            g: g * 255,\n            b: b * 255\n        };\n    }\n\n    // `rgbToHex`\n    // Converts an RGB color to hex\n    // Assumes r, g, and b are contained in the set [0, 255]\n    // Returns a 3 or 6 character hex\n    function rgbToHex(r, g, b, allow3Char) {\n        var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))];\n\n        // Return a 3 character hex if possible\n        if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {\n            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);\n        }\n        return hex.join(\"\");\n    }\n\n    // `rgbaToHex`\n    // Converts an RGBA color plus alpha transparency to hex\n    // Assumes r, g, b are contained in the set [0, 255] and\n    // a in [0, 1]. Returns a 4 or 8 character rgba hex\n    function rgbaToHex(r, g, b, a, allow4Char) {\n        var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16)), pad2(convertDecimalToHex(a))];\n\n        // Return a 4 character hex if possible\n        if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) {\n            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);\n        }\n        return hex.join(\"\");\n    }\n\n    // `rgbaToArgbHex`\n    // Converts an RGBA color to an ARGB Hex8 string\n    // Rarely used, but required for \"toFilter()\"\n    function rgbaToArgbHex(r, g, b, a) {\n        var hex = [pad2(convertDecimalToHex(a)), pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))];\n        return hex.join(\"\");\n    }\n\n    // `equals`\n    // Can be called with any tinycolor input\n    tinycolor.equals = function (color1, color2) {\n        if (!color1 || !color2) return false;\n        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();\n    };\n    tinycolor.random = function () {\n        return tinycolor.fromRatio({\n            r: Math.random(),\n            g: Math.random(),\n            b: Math.random()\n        });\n    };\n\n    // Modification Functions\n    // ----------------------\n    // Thanks to less.js for some of the basics here\n    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>\n\n    function _desaturate(color, amount) {\n        amount = amount === 0 ? 0 : amount || 10;\n        var hsl = tinycolor(color).toHsl();\n        hsl.s -= amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    }\n    function _saturate(color, amount) {\n        amount = amount === 0 ? 0 : amount || 10;\n        var hsl = tinycolor(color).toHsl();\n        hsl.s += amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    }\n    function _greyscale(color) {\n        return tinycolor(color).desaturate(100);\n    }\n    function _lighten(color, amount) {\n        amount = amount === 0 ? 0 : amount || 10;\n        var hsl = tinycolor(color).toHsl();\n        hsl.l += amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    }\n    function _brighten(color, amount) {\n        amount = amount === 0 ? 0 : amount || 10;\n        var rgb = tinycolor(color).toRgb();\n        rgb.r = Math.max(0, Math.min(255, rgb.r - Math.round(255 * -(amount / 100))));\n        rgb.g = Math.max(0, Math.min(255, rgb.g - Math.round(255 * -(amount / 100))));\n        rgb.b = Math.max(0, Math.min(255, rgb.b - Math.round(255 * -(amount / 100))));\n        return tinycolor(rgb);\n    }\n    function _darken(color, amount) {\n        amount = amount === 0 ? 0 : amount || 10;\n        var hsl = tinycolor(color).toHsl();\n        hsl.l -= amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    }\n\n    // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.\n    // Values outside of this range will be wrapped into this range.\n    function _spin(color, amount) {\n        var hsl = tinycolor(color).toHsl();\n        var hue = (hsl.h + amount) % 360;\n        hsl.h = hue < 0 ? 360 + hue : hue;\n        return tinycolor(hsl);\n    }\n\n    // Combination Functions\n    // ---------------------\n    // Thanks to jQuery xColor for some of the ideas behind these\n    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>\n\n    function _complement(color) {\n        var hsl = tinycolor(color).toHsl();\n        hsl.h = (hsl.h + 180) % 360;\n        return tinycolor(hsl);\n    }\n    function polyad(color, number) {\n        if (isNaN(number) || number <= 0) {\n            throw new Error(\"Argument to polyad must be a positive number\");\n        }\n        var hsl = tinycolor(color).toHsl();\n        var result = [tinycolor(color)];\n        var step = 360 / number;\n        for (var i = 1; i < number; i++) {\n            result.push(tinycolor({\n                h: (hsl.h + i * step) % 360,\n                s: hsl.s,\n                l: hsl.l\n            }));\n        }\n        return result;\n    }\n    function _splitcomplement(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [tinycolor(color), tinycolor({\n            h: (h + 72) % 360,\n            s: hsl.s,\n            l: hsl.l\n        }), tinycolor({\n            h: (h + 216) % 360,\n            s: hsl.s,\n            l: hsl.l\n        })];\n    }\n    function _analogous(color, results, slices) {\n        results = results || 6;\n        slices = slices || 30;\n        var hsl = tinycolor(color).toHsl();\n        var part = 360 / slices;\n        var ret = [tinycolor(color)];\n        for (hsl.h = (hsl.h - (part * results >> 1) + 720) % 360; --results;) {\n            hsl.h = (hsl.h + part) % 360;\n            ret.push(tinycolor(hsl));\n        }\n        return ret;\n    }\n    function _monochromatic(color, results) {\n        results = results || 6;\n        var hsv = tinycolor(color).toHsv();\n        var h = hsv.h,\n            s = hsv.s,\n            v = hsv.v;\n        var ret = [];\n        var modification = 1 / results;\n        while (results--) {\n            ret.push(tinycolor({\n                h: h,\n                s: s,\n                v: v\n            }));\n            v = (v + modification) % 1;\n        }\n        return ret;\n    }\n\n    // Utility Functions\n    // ---------------------\n\n    tinycolor.mix = function (color1, color2, amount) {\n        amount = amount === 0 ? 0 : amount || 50;\n        var rgb1 = tinycolor(color1).toRgb();\n        var rgb2 = tinycolor(color2).toRgb();\n        var p = amount / 100;\n        var 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 tinycolor(rgba);\n    };\n\n    // Readability Functions\n    // ---------------------\n    // <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)\n\n    // `contrast`\n    // Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)\n    tinycolor.readability = function (color1, color2) {\n        var c1 = tinycolor(color1);\n        var c2 = tinycolor(color2);\n        return (Math.max(c1.getLuminance(), c2.getLuminance()) + 0.05) / (Math.min(c1.getLuminance(), c2.getLuminance()) + 0.05);\n    };\n\n    // `isReadable`\n    // Ensure that foreground and background color combinations meet WCAG2 guidelines.\n    // The third argument is an optional Object.\n    //      the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';\n    //      the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.\n    // If the entire object is absent, isReadable defaults to {level:\"AA\",size:\"small\"}.\n\n    // *Example*\n    //    tinycolor.isReadable(\"#000\", \"#111\") => false\n    //    tinycolor.isReadable(\"#000\", \"#111\",{level:\"AA\",size:\"large\"}) => false\n    tinycolor.isReadable = function (color1, color2, wcag2) {\n        var readability = tinycolor.readability(color1, color2);\n        var wcag2Parms, out;\n        out = false;\n        wcag2Parms = validateWCAG2Parms(wcag2);\n        switch (wcag2Parms.level + wcag2Parms.size) {\n            case \"AAsmall\":\n            case \"AAAlarge\":\n                out = readability >= 4.5;\n                break;\n            case \"AAlarge\":\n                out = readability >= 3;\n                break;\n            case \"AAAsmall\":\n                out = readability >= 7;\n                break;\n        }\n        return out;\n    };\n\n    // `mostReadable`\n    // Given a base color and a list of possible foreground or background\n    // colors for that base, returns the most readable color.\n    // Optionally returns Black or White if the most readable color is unreadable.\n    // *Example*\n    //    tinycolor.mostReadable(tinycolor.mostReadable(\"#123\", [\"#124\", \"#125\"],{includeFallbackColors:false}).toHexString(); // \"#112255\"\n    //    tinycolor.mostReadable(tinycolor.mostReadable(\"#123\", [\"#124\", \"#125\"],{includeFallbackColors:true}).toHexString();  // \"#ffffff\"\n    //    tinycolor.mostReadable(\"#a8015a\", [\"#faf3f3\"],{includeFallbackColors:true,level:\"AAA\",size:\"large\"}).toHexString(); // \"#faf3f3\"\n    //    tinycolor.mostReadable(\"#a8015a\", [\"#faf3f3\"],{includeFallbackColors:true,level:\"AAA\",size:\"small\"}).toHexString(); // \"#ffffff\"\n    tinycolor.mostReadable = function (baseColor, colorList, args) {\n        var bestColor = null;\n        var bestScore = 0;\n        var readability;\n        var includeFallbackColors, level, size;\n        args = args || {};\n        includeFallbackColors = args.includeFallbackColors;\n        level = args.level;\n        size = args.size;\n        for (var i = 0; i < colorList.length; i++) {\n            readability = tinycolor.readability(baseColor, colorList[i]);\n            if (readability > bestScore) {\n                bestScore = readability;\n                bestColor = tinycolor(colorList[i]);\n            }\n        }\n        if (tinycolor.isReadable(baseColor, bestColor, {\n            level: level,\n            size: size\n        }) || !includeFallbackColors) {\n            return bestColor;\n        } else {\n            args.includeFallbackColors = false;\n            return tinycolor.mostReadable(baseColor, [\"#fff\", \"#000\"], args);\n        }\n    };\n\n    // Big List of Colors\n    // ------------------\n    // <https://www.w3.org/TR/css-color-4/#named-colors>\n    var names = tinycolor.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: \"663399\",\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    };\n\n    // Make it easy to access colors via `hexNames[hex]`\n    var hexNames = tinycolor.hexNames = flip(names);\n\n    // Utilities\n    // ---------\n\n    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`\n    function flip(o) {\n        var flipped = {};\n        for (var i in o) {\n            if (o.hasOwnProperty(i)) {\n                flipped[o[i]] = i;\n            }\n        }\n        return flipped;\n    }\n\n    // Return a valid alpha value [0,1] with all invalid values being set to 1\n    function boundAlpha(a) {\n        a = parseFloat(a);\n        if (isNaN(a) || a < 0 || a > 1) {\n            a = 1;\n        }\n        return a;\n    }\n\n    // Take input from [0, n] and return it as [0, 1]\n    function bound01(n, max) {\n        if (isOnePointZero(n)) n = \"100%\";\n        var processPercent = isPercentage(n);\n        n = Math.min(max, Math.max(0, parseFloat(n)));\n\n        // Automatically convert percentage into number\n        if (processPercent) {\n            n = parseInt(n * max, 10) / 100;\n        }\n\n        // Handle floating point rounding errors\n        if (Math.abs(n - max) < 0.000001) {\n            return 1;\n        }\n\n        // Convert into [0, 1] range if it isn't already\n        return n % max / parseFloat(max);\n    }\n\n    // Force a number between 0 and 1\n    function clamp01(val) {\n        return Math.min(1, Math.max(0, val));\n    }\n\n    // Parse a base-16 hex value into a base-10 integer\n    function parseIntFromHex(val) {\n        return parseInt(val, 16);\n    }\n\n    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\n    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>\n    function isOnePointZero(n) {\n        return typeof n == \"string\" && n.indexOf(\".\") != -1 && parseFloat(n) === 1;\n    }\n\n    // Check to see if string passed in is a percentage\n    function isPercentage(n) {\n        return typeof n === \"string\" && n.indexOf(\"%\") != -1;\n    }\n\n    // Force a hex value to have 2 characters\n    function pad2(c) {\n        return c.length == 1 ? \"0\" + c : \"\" + c;\n    }\n\n    // Replace a decimal with it's percentage value\n    function convertToPercentage(n) {\n        if (n <= 1) {\n            n = n * 100 + \"%\";\n        }\n        return n;\n    }\n\n    // Converts a decimal to a hex value\n    function convertDecimalToHex(d) {\n        return Math.round(parseFloat(d) * 255).toString(16);\n    }\n    // Converts a hex value to a decimal\n    function convertHexToDecimal(h) {\n        return parseIntFromHex(h) / 255;\n    }\n    var matchers = function () {\n        // <http://www.w3.org/TR/css3-values/#integers>\n        var CSS_INTEGER = \"[-\\\\+]?\\\\d+%?\";\n\n        // <http://www.w3.org/TR/css3-values/#number-value>\n        var CSS_NUMBER = \"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\";\n\n        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.\n        var CSS_UNIT = \"(?:\" + CSS_NUMBER + \")|(?:\" + CSS_INTEGER + \")\";\n\n        // Actual matching.\n        // Parentheses and commas are optional, but not required.\n        // Whitespace can take the place of commas or opening paren\n        var PERMISSIVE_MATCH3 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n        var PERMISSIVE_MATCH4 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n        return {\n            CSS_UNIT: new RegExp(CSS_UNIT),\n            rgb: new RegExp(\"rgb\" + PERMISSIVE_MATCH3),\n            rgba: new RegExp(\"rgba\" + PERMISSIVE_MATCH4),\n            hsl: new RegExp(\"hsl\" + PERMISSIVE_MATCH3),\n            hsla: new RegExp(\"hsla\" + PERMISSIVE_MATCH4),\n            hsv: new RegExp(\"hsv\" + PERMISSIVE_MATCH3),\n            hsva: new RegExp(\"hsva\" + PERMISSIVE_MATCH4),\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            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\n    // `isValidCSSUnit`\n    // Take in a single string / number and check to see if it looks like a CSS unit\n    // (see `matchers` above for definition).\n    function isValidCSSUnit(color) {\n        return !!matchers.CSS_UNIT.exec(color);\n    }\n\n    // `stringInputToObject`\n    // Permissive string parsing.  Take in a number of formats, and output an object\n    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`\n    function stringInputToObject(color) {\n        color = color.replace(trimLeft, \"\").replace(trimRight, \"\").toLowerCase();\n        var named = false;\n        if (names[color]) {\n            color = names[color];\n            named = true;\n        } else if (color == \"transparent\") {\n            return {\n                r: 0,\n                g: 0,\n                b: 0,\n                a: 0,\n                format: \"name\"\n            };\n        }\n\n        // Try to match string input using regular expressions.\n        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]\n        // Just return an object and let the conversion functions handle that.\n        // This way the result will be the same whether the tinycolor is initialized with string or object.\n        var match;\n        if (match = matchers.rgb.exec(color)) {\n            return {\n                r: match[1],\n                g: match[2],\n                b: match[3]\n            };\n        }\n        if (match = matchers.rgba.exec(color)) {\n            return {\n                r: match[1],\n                g: match[2],\n                b: match[3],\n                a: match[4]\n            };\n        }\n        if (match = matchers.hsl.exec(color)) {\n            return {\n                h: match[1],\n                s: match[2],\n                l: match[3]\n            };\n        }\n        if (match = matchers.hsla.exec(color)) {\n            return {\n                h: match[1],\n                s: match[2],\n                l: match[3],\n                a: match[4]\n            };\n        }\n        if (match = matchers.hsv.exec(color)) {\n            return {\n                h: match[1],\n                s: match[2],\n                v: match[3]\n            };\n        }\n        if (match = matchers.hsva.exec(color)) {\n            return {\n                h: match[1],\n                s: match[2],\n                v: match[3],\n                a: match[4]\n            };\n        }\n        if (match = matchers.hex8.exec(color)) {\n            return {\n                r: parseIntFromHex(match[1]),\n                g: parseIntFromHex(match[2]),\n                b: parseIntFromHex(match[3]),\n                a: convertHexToDecimal(match[4]),\n                format: named ? \"name\" : \"hex8\"\n            };\n        }\n        if (match = matchers.hex6.exec(color)) {\n            return {\n                r: parseIntFromHex(match[1]),\n                g: parseIntFromHex(match[2]),\n                b: parseIntFromHex(match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n        if (match = matchers.hex4.exec(color)) {\n            return {\n                r: parseIntFromHex(match[1] + \"\" + match[1]),\n                g: parseIntFromHex(match[2] + \"\" + match[2]),\n                b: parseIntFromHex(match[3] + \"\" + match[3]),\n                a: convertHexToDecimal(match[4] + \"\" + match[4]),\n                format: named ? \"name\" : \"hex8\"\n            };\n        }\n        if (match = matchers.hex3.exec(color)) {\n            return {\n                r: parseIntFromHex(match[1] + \"\" + match[1]),\n                g: parseIntFromHex(match[2] + \"\" + match[2]),\n                b: parseIntFromHex(match[3] + \"\" + match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n        return false;\n    }\n    function validateWCAG2Parms(parms) {\n        // return valid WCAG2 parms for isReadable.\n        // If input parms are invalid, return {\"level\":\"AA\", \"size\":\"small\"}\n        var level, size;\n        parms = parms || {\n            level: \"AA\",\n            size: \"small\"\n        };\n        level = (parms.level || \"AA\").toUpperCase();\n        size = (parms.size || \"small\").toLowerCase();\n        if (level !== \"AA\" && level !== \"AAA\") {\n            level = \"AA\";\n        }\n        if (size !== \"small\" && size !== \"large\") {\n            size = \"small\";\n        }\n        return {\n            level: level,\n            size: size\n        };\n    }\n\n    return tinycolor;\n\n}));\n","jquery/bootstrap/tab.js":"/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): tab.js and base-component.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\ndefine([\n    \"./util/index\",\n    \"./dom/event-handler\",\n    \"./dom/selector-engine\"\n], function(Util, EventHandler, SelectorEngine) {\n    'use strict';\n\n    const defineJQueryPlugin = Util.defineJQueryPlugin;\n    const executeAfterTransition = Util.executeAfterTransition;\n    const getElement = Util.getElement;\n    const getElementFromSelector = Util.getElementFromSelector;\n    const isDisabled = Util.isDisabled;\n    const reflow = Util.reflow;\n\n    /**\n     * ------------------------------------------------------------------------\n     * Constants\n     * ------------------------------------------------------------------------\n     */\n\n    const VERSION = '5.1.3';\n    const NAME = 'tab';\n    const DATA_KEY = 'bs.tab';\n    const EVENT_KEY = `.${DATA_KEY}`;\n    const DATA_API_KEY = '.data-api';\n\n    const EVENT_HIDE = `hide${EVENT_KEY}`;\n    const EVENT_HIDDEN = `hidden${EVENT_KEY}`;\n    const EVENT_SHOW = `show${EVENT_KEY}`;\n    const EVENT_SHOWN = `shown${EVENT_KEY}`;\n    const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;\n\n    const CLASS_NAME_DROPDOWN_MENU = 'dropdown-menu';\n    const CLASS_NAME_ACTIVE = 'active';\n    const CLASS_NAME_FADE = 'fade';\n    const CLASS_NAME_SHOW = 'show';\n\n    const SELECTOR_DROPDOWN = '.dropdown';\n    const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';\n    const SELECTOR_ACTIVE = '.active';\n    const SELECTOR_ACTIVE_UL = ':scope > li > .active';\n    const SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"tab\"], [data-bs-toggle=\"pill\"], [data-bs-toggle=\"list\"]';\n    const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';\n    const SELECTOR_DROPDOWN_ACTIVE_CHILD = ':scope > .dropdown-menu .active';\n\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n    function Tab(element) {\n        element = getElement(element);\n\n        if (!element) {\n            return;\n        }\n\n        this._element = element;\n        Data.set(this._element, DATA_KEY, this);\n    }\n\n    // Getters\n\n    Tab.VERSION = VERSION;\n\n    Tab.NAME = NAME;\n\n    Tab.DATA_KEY = 'bs.' + Tab.NAME;\n\n    Tab.EVENT_KEY = '.' + Tab.DATA_KEY;\n\n    // Public\n\n    Tab.prototype.dispose = function() {\n        Data.remove(this._element, this.constructor.DATA_KEY);\n        EventHandler.off(this._element, this.constructor.EVENT_KEY);\n\n        Object.getOwnPropertyNames(this).forEach(propertyName => {\n            this[propertyName] = null;\n        })\n    }\n\n    Tab.prototype._queueCallback = function(callback, element, isAnimated = true) {\n        executeAfterTransition(callback, element, isAnimated);\n    }\n\n    Tab.prototype.show = function() {\n        if ((this._element.parentNode &&\n            this._element.parentNode.nodeType === Node.ELEMENT_NODE &&\n            this._element.classList.contains(CLASS_NAME_ACTIVE))) {\n            return;\n        }\n\n        let previous;\n        const target = getElementFromSelector(this._element);\n        const listElement = this._element.closest(SELECTOR_NAV_LIST_GROUP);\n\n        if (listElement) {\n            const itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? SELECTOR_ACTIVE_UL : SELECTOR_ACTIVE;\n            previous = SelectorEngine.find(itemSelector, listElement);\n            previous = previous[previous.length - 1];\n        }\n\n        const hideEvent = previous ?\n            EventHandler.trigger(previous, EVENT_HIDE, {\n                relatedTarget: this._element\n            }) :\n            null;\n\n        const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, {\n            relatedTarget: previous\n        });\n\n        if (showEvent.defaultPrevented || (hideEvent !== null && hideEvent.defaultPrevented)) {\n            return;\n        }\n\n        this._activate(this._element, listElement);\n\n        const complete = () => {\n            EventHandler.trigger(previous, EVENT_HIDDEN, {\n                relatedTarget: this._element\n            });\n            EventHandler.trigger(this._element, EVENT_SHOWN, {\n                relatedTarget: previous\n            });\n        };\n\n        if (target) {\n            this._activate(target, target.parentNode, complete);\n        } else {\n            complete();\n        }\n    }\n\n    // Private\n\n    Tab.prototype._activate = function(element, container, callback) {\n        const activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ?\n            SelectorEngine.find(SELECTOR_ACTIVE_UL, container) :\n            SelectorEngine.children(container, SELECTOR_ACTIVE);\n\n        const active = activeElements[0];\n        const isTransitioning = callback && (active && active.classList.contains(CLASS_NAME_FADE));\n\n        const complete = () => this._transitionComplete(element, active, callback);\n\n        if (active && isTransitioning) {\n            active.classList.remove(CLASS_NAME_SHOW);\n            this._queueCallback(complete, element, true);\n        } else {\n            complete();\n        }\n    }\n\n    Tab.prototype._transitionComplete = function(element, active, callback) {\n        if (active) {\n            active.classList.remove(CLASS_NAME_ACTIVE);\n\n            const dropdownChild = SelectorEngine.findOne(SELECTOR_DROPDOWN_ACTIVE_CHILD, active.parentNode);\n\n            if (dropdownChild) {\n                dropdownChild.classList.remove(CLASS_NAME_ACTIVE);\n            }\n\n            if (active.getAttribute('role') === 'tab') {\n                active.setAttribute('aria-selected', false);\n            }\n        }\n\n        element.classList.add(CLASS_NAME_ACTIVE);\n        if (element.getAttribute('role') === 'tab') {\n            element.setAttribute('aria-selected', true);\n        }\n\n        reflow(element);\n\n        if (element.classList.contains(CLASS_NAME_FADE)) {\n            element.classList.add(CLASS_NAME_SHOW);\n        }\n\n        let parent = element.parentNode;\n        if (parent && parent.nodeName === 'LI') {\n            parent = parent.parentNode;\n        }\n\n        if (parent && parent.classList.contains(CLASS_NAME_DROPDOWN_MENU)) {\n            const dropdownElement = element.closest(SELECTOR_DROPDOWN);\n\n            if (dropdownElement) {\n                SelectorEngine.find(SELECTOR_DROPDOWN_TOGGLE, dropdownElement)\n                    .forEach(dropdown => dropdown.classList.add(CLASS_NAME_ACTIVE));\n            }\n\n            element.setAttribute('aria-expanded', true);\n        }\n\n        if (callback) {\n            callback();\n        }\n    }\n\n    // Static\n\n    Tab.getInstance = function(element) {\n        return Data.get(getElement(element), this.DATA_KEY);\n    }\n\n    Tab.getOrCreateInstance = function(element, config = {}) {\n        return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null);\n    }\n\n    Tab.jQueryInterface = function(config) {\n        return this.each(function () {\n            const data = Tab.getOrCreateInstance(this);\n\n            if (typeof config === 'string') {\n                if (typeof data[config] === 'undefined') {\n                    throw new TypeError(`No method named \"${config}\"`);\n                }\n\n                data[config]();\n            }\n        })\n    }\n\n    /**\n     * ------------------------------------------------------------------------\n     * Data Api implementation\n     * ------------------------------------------------------------------------\n     */\n\n    EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n        if (['A', 'AREA'].includes(this.tagName)) {\n            event.preventDefault();\n        }\n\n        if (isDisabled(this)) {\n            return;\n        }\n\n        const data = Tab.getOrCreateInstance(this);\n        data.show();\n    })\n\n    /**\n     * ------------------------------------------------------------------------\n     * jQuery\n     * ------------------------------------------------------------------------\n     * add .Tab to jQuery only if jQuery is present\n     */\n\n    defineJQueryPlugin(Tab);\n\n    return Tab;\n});\n","jquery/bootstrap/collapse.js":"/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): collapse.js and base-component.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\ndefine([\n    \"jquery\",\n    \"./util/index\",\n    \"./dom/data\",\n    \"./dom/event-handler\",\n    \"./dom/manipulator\",\n    \"./dom/selector-engine\"\n], function($, Util, Data, EventHandler, Manipulator, SelectorEngine) {\n    'use strict';\n\n    const defineJQueryPlugin = Util.defineJQueryPlugin;\n    const executeAfterTransition = Util.executeAfterTransition;\n    const getElement = Util.getElement;\n    const getSelectorFromElement = Util.getSelectorFromElement;\n    const getElementFromSelector = Util.getElementFromSelector;\n    const reflow = Util.reflow;\n    const typeCheckConfig = Util.typeCheckConfig;\n\n    /**\n     * ------------------------------------------------------------------------\n     * Constants\n     * ------------------------------------------------------------------------\n     */\n\n    const VERSION = '5.1.3';\n    const NAME = 'collapse';\n    const DATA_KEY = 'bs.collapse';\n    const EVENT_KEY = `.${DATA_KEY}`;\n    const DATA_API_KEY = '.data-api';\n\n    const Default = {\n        toggle: true,\n        parent: null\n    };\n\n    const DefaultType = {\n        toggle: 'boolean',\n        parent: '(null|element)'\n    };\n\n    const EVENT_SHOW = `show${EVENT_KEY}`;\n    const EVENT_SHOWN = `shown${EVENT_KEY}`;\n    const EVENT_HIDE = `hide${EVENT_KEY}`;\n    const EVENT_HIDDEN = `hidden${EVENT_KEY}`;\n    const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;\n\n    const CLASS_NAME_SHOW = 'show';\n    const CLASS_NAME_COLLAPSE = 'collapse';\n    const CLASS_NAME_COLLAPSING = 'collapsing';\n    const CLASS_NAME_COLLAPSED = 'collapsed';\n    const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;\n    const CLASS_NAME_HORIZONTAL = 'collapse-horizontal';\n\n    const WIDTH = 'width';\n    const HEIGHT = 'height';\n\n    const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';\n    const SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"collapse\"]';\n\n    /**\n     * ------------------------------------------------------------------------\n     * Class Definition\n     * ------------------------------------------------------------------------\n     */\n\n    var Collapse = function(element, config) {\n        element = getElement(element);\n\n        if (!element) {\n            return;\n        }\n\n        this._element = element;\n        Data.set(this._element, DATA_KEY, this);\n\n        this._isTransitioning = false;\n        this._config = this._getConfig(config);\n        this._triggerArray = [];\n\n        const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE);\n\n        for (let i = 0, len = toggleList.length; i < len; i++) {\n            const elem = toggleList[i];\n            const selector = getSelectorFromElement(elem);\n            const filterElement = SelectorEngine.find(selector)\n                .filter(foundElem => foundElem === this._element);\n\n            if (selector !== null && filterElement.length) {\n                this._selector = selector;\n                this._triggerArray.push(elem);\n            }\n        }\n\n        this._initializeChildren();\n\n        if (!this._config.parent) {\n            this._addAriaAndCollapsedClass(this._triggerArray, this._isShown());\n        }\n\n        if (this._config.toggle) {\n            this.toggle();\n        }\n    }\n\n    // Getters\n\n    Collapse.VERSION = VERSION;\n\n    Collapse.Default = Default;\n\n    Collapse.NAME = NAME;\n\n    Collapse.DATA_KEY = 'bs.' + Collapse.NAME;\n\n    Collapse.EVENT_KEY = '.' + Collapse.DATA_KEY;\n\n    // Public\n\n    Collapse.prototype.dispose = function() {\n        Data.remove(this._element, this.constructor.DATA_KEY);\n        EventHandler.off(this._element, this.constructor.EVENT_KEY);\n\n        Object.getOwnPropertyNames(this).forEach(propertyName => {\n            this[propertyName] = null;\n        })\n    }\n\n    Collapse.prototype._queueCallback = function(callback, element, isAnimated = true) {\n        executeAfterTransition(callback, element, isAnimated);\n    }\n\n    Collapse.prototype.toggle = function() {\n        if (this._isShown()) {\n            this.hide();\n        } else {\n            this.show();\n        }\n    }\n\n    Collapse.prototype.show = function() {\n        if (this._isTransitioning || this._isShown()) {\n            return;\n        }\n\n        let actives = [];\n        let activesData;\n\n        if (this._config.parent) {\n            const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);\n            actives = SelectorEngine.find(SELECTOR_ACTIVES, this._config.parent).filter(elem => !children.includes(elem)); // remove children if greater depth\n        }\n\n        const container = SelectorEngine.findOne(this._selector);\n        if (actives.length) {\n            const tempActiveData = actives.find(elem => container !== elem);\n            activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null;\n\n            if (activesData && activesData._isTransitioning) {\n                return;\n            }\n        }\n\n        const startEvent = EventHandler.trigger(this._element, EVENT_SHOW);\n        if (startEvent.defaultPrevented) {\n            return;\n        }\n\n        actives.forEach(elemActive => {\n            if (container !== elemActive) {\n                Collapse.getOrCreateInstance(elemActive, {toggle: false}).hide();\n            }\n\n            if (!activesData) {\n                Data.set(elemActive, DATA_KEY, null);\n            }\n        })\n\n        const dimension = this._getDimension();\n\n        this._element.classList.remove(CLASS_NAME_COLLAPSE);\n        this._element.classList.add(CLASS_NAME_COLLAPSING);\n\n        this._element.style[dimension] = 0;\n\n        this._addAriaAndCollapsedClass(this._triggerArray, true);\n        this._isTransitioning = true;\n\n        const complete = () => {\n            this._isTransitioning = false;\n\n            this._element.classList.remove(CLASS_NAME_COLLAPSING);\n            this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);\n\n            this._element.style[dimension] = '';\n\n            EventHandler.trigger(this._element, EVENT_SHOWN);\n        };\n\n        const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);\n        const scrollSize = `scroll${capitalizedDimension}`;\n\n        this._queueCallback(complete, this._element, true);\n        this._element.style[dimension] = `${this._element[scrollSize]}px`;\n    }\n\n    Collapse.prototype.hide = function() {\n        if (this._isTransitioning || !this._isShown()) {\n            return;\n        }\n\n        const startEvent = EventHandler.trigger(this._element, EVENT_HIDE);\n        if (startEvent.defaultPrevented) {\n            return;\n        }\n\n        const dimension = this._getDimension();\n\n        this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`;\n\n        reflow(this._element);\n\n        this._element.classList.add(CLASS_NAME_COLLAPSING);\n        this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW);\n\n        const triggerArrayLength = this._triggerArray.length;\n        for (let i = 0; i < triggerArrayLength; i++) {\n            const trigger = this._triggerArray[i];\n            const elem = getElementFromSelector(trigger);\n\n            if (elem && !this._isShown(elem)) {\n                this._addAriaAndCollapsedClass([trigger], false);\n            }\n        }\n\n        this._isTransitioning = true;\n\n        const complete = () => {\n            this._isTransitioning = false;\n            this._element.classList.remove(CLASS_NAME_COLLAPSING);\n            this._element.classList.add(CLASS_NAME_COLLAPSE);\n            EventHandler.trigger(this._element, EVENT_HIDDEN);\n        };\n\n        this._element.style[dimension] = '';\n\n        this._queueCallback(complete, this._element, true);\n    }\n\n    Collapse.prototype._isShown = function(element = this._element) {\n        return element.classList.contains(CLASS_NAME_SHOW);\n    }\n\n    // Private\n\n    Collapse.prototype._getConfig = function(config) {\n        config = {\n            ...Default,\n            ...Manipulator.getDataAttributes(this._element),\n            ...config\n        };\n        config.toggle = Boolean(config.toggle); // Coerce string values\n        config.parent = getElement(config.parent);\n        typeCheckConfig(NAME, config, DefaultType);\n        return config;\n    }\n\n    Collapse.prototype._getDimension = function() {\n        return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT;\n    }\n\n    Collapse.prototype._initializeChildren = function() {\n        if (!this._config.parent) {\n            return;\n        }\n\n        const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);\n        SelectorEngine.find(SELECTOR_DATA_TOGGLE, this._config.parent).filter(elem => !children.includes(elem))\n            .forEach(element => {\n                const selected = getElementFromSelector(element);\n\n                if (selected) {\n                    this._addAriaAndCollapsedClass([element], this._isShown(selected));\n                }\n            })\n    }\n\n    Collapse.prototype._addAriaAndCollapsedClass = function(triggerArray, isOpen) {\n        if (!triggerArray.length) {\n            return;\n        }\n\n        triggerArray.forEach(elem => {\n            if (isOpen) {\n                elem.classList.remove(CLASS_NAME_COLLAPSED);\n            } else {\n                elem.classList.add(CLASS_NAME_COLLAPSED);\n            }\n\n            elem.setAttribute('aria-expanded', isOpen);\n        })\n    }\n\n    // Static\n\n    Collapse.getInstance = function(element) {\n        return Data.get(getElement(element), this.DATA_KEY);\n    }\n\n    Collapse.getOrCreateInstance = function(element, config = {}) {\n        return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null);\n    }\n\n    Collapse.jQueryInterface = function(config) {\n        return this.each(function () {\n            const _config = {};\n            if (typeof config === 'string' && /show|hide/.test(config)) {\n                _config.toggle = false;\n            }\n\n            const data = Collapse.getOrCreateInstance(this, _config);\n\n            if (typeof config === 'string') {\n                if (typeof data[config] === 'undefined') {\n                    throw new TypeError(`No method named \"${config}\"`);\n                }\n\n                data[config]();\n            }\n        })\n    }\n\n    /**\n     * ------------------------------------------------------------------------\n     * Data Api implementation\n     * ------------------------------------------------------------------------\n     */\n\n    EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {\n        // preventDefault only for <a> elements (which change the URL) not inside the collapsible element\n        if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) {\n            event.preventDefault();\n        }\n\n        const selector = getSelectorFromElement(this);\n        const selectorElements = SelectorEngine.find(selector);\n\n        selectorElements.forEach(element => {\n            Collapse.getOrCreateInstance(element, {toggle: false}).toggle();\n        })\n    })\n\n    /**\n     * ------------------------------------------------------------------------\n     * jQuery\n     * ------------------------------------------------------------------------\n     * add .Collapse to jQuery only if jQuery is present\n     */\n\n    defineJQueryPlugin(Collapse);\n\n    return Collapse;\n});\n","jquery/bootstrap/util/index.js":"/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): util/index.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\n\ndefine([\n    \"jquery\",\n    'domReady!'\n], function() {\n    'use strict';\n\n    const MAX_UID = 1000000;\n    const MILLISECONDS_MULTIPLIER = 1000;\n    const TRANSITION_END = 'transitionend';\n\n    // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n    const toType = obj => {\n        if (obj === null || obj === undefined) {\n            return `${obj}`\n        }\n\n        return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase()\n    };\n\n    /**\n     * --------------------------------------------------------------------------\n     * Public Util Api\n     * --------------------------------------------------------------------------\n     */\n\n    const getUID = prefix => {\n        do {\n            prefix += Math.floor(Math.random() * MAX_UID)\n        } while (document.getElementById(prefix))\n\n        return prefix\n    };\n\n    const getSelector = element => {\n        let selector = element.getAttribute('data-bs-target');\n\n        if (!selector || selector === '#') {\n            let hrefAttr = element.getAttribute('href');\n\n            // The only valid content that could double as a selector are IDs or classes,\n            // so everything starting with `#` or `.`. If a \"real\" URL is used as the selector,\n            // `document.querySelector` will rightfully complain it is invalid.\n            // See https://github.com/twbs/bootstrap/issues/32273\n            if (!hrefAttr || (!hrefAttr.includes('#') && !hrefAttr.startsWith('.'))) {\n                return null\n            }\n\n            // Just in case some CMS puts out a full URL with the anchor appended\n            if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {\n                hrefAttr = `#${hrefAttr.split('#')[1]}`\n            }\n\n            selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null\n        }\n\n        return selector\n    };\n\n    const getSelectorFromElement = element => {\n        const selector = getSelector(element);\n\n        if (selector) {\n            return document.querySelector(selector) ? selector : null\n        }\n\n        return null\n    };\n\n    const getElementFromSelector = element => {\n        const selector = getSelector(element);\n\n        return selector ? document.querySelector(selector) : null\n    };\n\n    const getTransitionDurationFromElement = element => {\n        if (!element) {\n            return 0\n        }\n\n        // Get transition-duration of the element\n        let {transitionDuration, transitionDelay} = window.getComputedStyle(element);\n\n        const floatTransitionDuration = Number.parseFloat(transitionDuration);\n        const floatTransitionDelay = Number.parseFloat(transitionDelay);\n\n        // Return 0 if element or transition duration is not found\n        if (!floatTransitionDuration && !floatTransitionDelay) {\n            return 0\n        }\n\n        // If multiple durations are defined, take the first\n        transitionDuration = transitionDuration.split(',')[0]\n        transitionDelay = transitionDelay.split(',')[0]\n\n        return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER\n    };\n\n    const triggerTransitionEnd = element => {\n        element.dispatchEvent(new Event(TRANSITION_END))\n    };\n\n    const isElement = obj => {\n        if (!obj || typeof obj !== 'object') {\n            return false\n        }\n\n        if (typeof obj.jquery !== 'undefined') {\n            obj = obj[0]\n        }\n\n        return typeof obj.nodeType !== 'undefined'\n    };\n\n    const getElement = obj => {\n        if (isElement(obj)) { // it's a jQuery object or a node element\n            return obj.jquery ? obj[0] : obj\n        }\n\n        if (typeof obj === 'string' && obj.length > 0) {\n            return document.querySelector(obj)\n        }\n\n        return null\n    };\n\n    const typeCheckConfig = (componentName, config, configTypes) => {\n        Object.keys(configTypes).forEach(property => {\n            const expectedTypes = configTypes[property];\n            const value = config[property];\n            const valueType = value && isElement(value) ? 'element' : toType(value);\n\n            if (!new RegExp(expectedTypes).test(valueType)) {\n                throw new TypeError(\n                    `${componentName.toUpperCase()}: Option \"${property}\" provided type \"${valueType}\" but expected type \"${expectedTypes}\".`\n                )\n            }\n        })\n    };\n\n    const isVisible = element => {\n        if (!isElement(element) || element.getClientRects().length === 0) {\n            return false\n        }\n\n        return getComputedStyle(element).getPropertyValue('visibility') === 'visible'\n    };\n\n    const isDisabled = element => {\n        if (!element || element.nodeType !== Node.ELEMENT_NODE) {\n            return true\n        }\n\n        if (element.classList.contains('disabled')) {\n            return true\n        }\n\n        if (typeof element.disabled !== 'undefined') {\n            return element.disabled\n        }\n\n        return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'\n    };\n\n    const findShadowRoot = element => {\n        if (!document.documentElement.attachShadow) {\n            return null\n        }\n\n        // Can find the shadow root otherwise it'll return the document\n        if (typeof element.getRootNode === 'function') {\n            const root = element.getRootNode();\n            return root instanceof ShadowRoot ? root : null\n        }\n\n        if (element instanceof ShadowRoot) {\n            return element\n        }\n\n        // when we don't find a shadow root\n        if (!element.parentNode) {\n            return null\n        }\n\n        return findShadowRoot(element.parentNode)\n    };\n\n    const noop = () => {};\n\n    /**\n     * Trick to restart an element's animation\n     *\n     * @param {HTMLElement} element\n     * @return void\n     *\n     * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation\n     */\n    const reflow = element => {\n        // eslint-disable-next-line no-unused-expressions\n        element.offsetHeight\n    };\n\n    const getjQuery = () => {\n        const {jQuery} = window;\n\n        if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {\n            return jQuery\n        }\n\n        return null\n    };\n\n    const DOMContentLoadedCallbacks = [];\n\n    const onDOMContentLoaded = callback => {\n        if (document.readyState === 'loading') {\n            // add listener on the first call when the document is in loading state\n            if (!DOMContentLoadedCallbacks.length) {\n                document.addEventListener('DOMContentLoaded', () => {\n                    DOMContentLoadedCallbacks.forEach(callback => callback())\n                })\n            }\n\n            DOMContentLoadedCallbacks.push(callback)\n        } else {\n            callback()\n        }\n    };\n\n    const isRTL = () => document.documentElement.dir === 'rtl';\n\n    const defineJQueryPlugin = plugin => {\n        onDOMContentLoaded(() => {\n            const $ = getjQuery();\n            /* istanbul ignore if */\n            if ($) {\n                const name = plugin.NAME;\n                const JQUERY_NO_CONFLICT = $.fn[name];\n                $.fn[name] = plugin.jQueryInterface\n                $.fn[name].Constructor = plugin\n                $.fn[name].noConflict = () => {\n                    $.fn[name] = JQUERY_NO_CONFLICT\n                    return plugin.jQueryInterface\n                }\n            }\n        })\n    };\n\n    const execute = callback => {\n        if (typeof callback === 'function') {\n            callback()\n        }\n    };\n\n    const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {\n        if (!waitForTransition) {\n            execute(callback)\n            return\n        }\n\n        const durationPadding = 5;\n        const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;\n\n        let called = false;\n\n        const handler = ({ target }) => {\n            if (target !== transitionElement) {\n                return\n            }\n\n            called = true\n            transitionElement.removeEventListener(TRANSITION_END, handler)\n            execute(callback)\n        };\n\n        transitionElement.addEventListener(TRANSITION_END, handler)\n        setTimeout(() => {\n            if (!called) {\n                triggerTransitionEnd(transitionElement)\n            }\n        }, emulatedDuration)\n    };\n\n    /**\n     * Return the previous/next element of a list.\n     *\n     * @param {array} list    The list of elements\n     * @param activeElement   The active element\n     * @param shouldGetNext   Choose to get next or previous element\n     * @param isCycleAllowed\n     * @return {Element|elem} The proper element\n     */\n    const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {\n        let index = list.indexOf(activeElement);\n\n        // if the element does not exist in the list return an element depending on the direction and if cycle is allowed\n        if (index === -1) {\n            return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0]\n        }\n\n        const listLength = list.length;\n\n        index += shouldGetNext ? 1 : -1\n\n        if (isCycleAllowed) {\n            index = (index + listLength) % listLength\n        }\n\n        return list[Math.max(0, Math.min(index, listLength - 1))]\n    };\n\n    return {\n        getElement,\n        getUID,\n        getSelectorFromElement,\n        getElementFromSelector,\n        getTransitionDurationFromElement,\n        triggerTransitionEnd,\n        isElement,\n        typeCheckConfig,\n        isVisible,\n        isDisabled,\n        findShadowRoot,\n        noop,\n        getNextActiveElement,\n        reflow,\n        getjQuery,\n        onDOMContentLoaded,\n        isRTL,\n        defineJQueryPlugin,\n        execute,\n        executeAfterTransition\n    };\n});\n","jquery/bootstrap/dom/data.js":"/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): dom/data.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\ndefine([], function() {\n    'use strict';\n\n    /**\n     * ------------------------------------------------------------------------\n     * Constants\n     * ------------------------------------------------------------------------\n     */\n\n    const elementMap = new Map();\n\n    return {\n        set: function (element, key, instance) {\n            if (!elementMap.has(element)) {\n                elementMap.set(element, new Map())\n            }\n\n            const instanceMap = elementMap.get(element);\n\n            // make it clear we only want one instance per element\n            // can be removed later when multiple key/instances are fine to be used\n            if (!instanceMap.has(key) && instanceMap.size !== 0) {\n                // eslint-disable-next-line no-console\n                console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)\n                return\n            }\n\n            instanceMap.set(key, instance)\n        },\n\n        get: function (element, key) {\n            if (elementMap.has(element)) {\n                return elementMap.get(element).get(key) || null\n            }\n\n            return null\n        },\n\n        remove: function (element, key) {\n            if (!elementMap.has(element)) {\n                return\n            }\n\n            const instanceMap = elementMap.get(element);\n\n            instanceMap.delete(key)\n\n            // free up element references if there are no instances left for an element\n            if (instanceMap.size === 0) {\n                elementMap.delete(element)\n            }\n        }\n    }\n});\n","jquery/bootstrap/dom/event-handler.js":"/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): dom/event-handler.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\ndefine([\n    \"../util/index\"\n], function(Util) {\n    'use strict';\n\n    const getjQuery = Util.getjQuery;\n\n    /**\n     * ------------------------------------------------------------------------\n     * Constants\n     * ------------------------------------------------------------------------\n     */\n\n    const namespaceRegex = /[^.]*(?=\\..*)\\.|.*/;\n    const stripNameRegex = /\\..*/;\n    const stripUidRegex = /::\\d+$/;\n    const eventRegistry = {}; // Events storage\n    let uidEvent = 1;\n    const customEvents = {\n        mouseenter: 'mouseover',\n        mouseleave: 'mouseout'\n    };\n    const customEventsRegex = /^(mouseenter|mouseleave)/i;\n    const nativeEvents = new Set([\n        'click',\n        'dblclick',\n        'mouseup',\n        'mousedown',\n        'contextmenu',\n        'mousewheel',\n        'DOMMouseScroll',\n        'mouseover',\n        'mouseout',\n        'mousemove',\n        'selectstart',\n        'selectend',\n        'keydown',\n        'keypress',\n        'keyup',\n        'orientationchange',\n        'touchstart',\n        'touchmove',\n        'touchend',\n        'touchcancel',\n        'pointerdown',\n        'pointermove',\n        'pointerup',\n        'pointerleave',\n        'pointercancel',\n        'gesturestart',\n        'gesturechange',\n        'gestureend',\n        'focus',\n        'blur',\n        'change',\n        'reset',\n        'select',\n        'submit',\n        'focusin',\n        'focusout',\n        'load',\n        'unload',\n        'beforeunload',\n        'resize',\n        'move',\n        'DOMContentLoaded',\n        'readystatechange',\n        'error',\n        'abort',\n        'scroll'\n    ]);\n\n    /**\n     * ------------------------------------------------------------------------\n     * Private methods\n     * ------------------------------------------------------------------------\n     */\n\n    function getUidEvent(element, uid) {\n        return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++\n    }\n\n    function getEvent(element) {\n        const uid = getUidEvent(element);\n\n        element.uidEvent = uid\n        eventRegistry[uid] = eventRegistry[uid] || {}\n\n        return eventRegistry[uid]\n    }\n\n    function bootstrapHandler(element, fn) {\n        return function handler(event) {\n            event.delegateTarget = element\n\n            if (handler.oneOff) {\n                EventHandler.off(element, event.type, fn)\n            }\n\n            return fn.apply(element, [event])\n        }\n    }\n\n    function bootstrapDelegationHandler(element, selector, fn) {\n        return function handler(event) {\n            const domElements = element.querySelectorAll(selector);\n\n            for (let {target} = event; target && target !== this; target = target.parentNode) {\n                for (let i = domElements.length; i--;) {\n                    if (domElements[i] === target) {\n                        event.delegateTarget = target\n\n                        if (handler.oneOff) {\n                            EventHandler.off(element, event.type, selector, fn)\n                        }\n\n                        return fn.apply(target, [event])\n                    }\n                }\n            }\n\n            // To please ESLint\n            return null\n        }\n    }\n\n    function findHandler(events, handler, delegationSelector = null) {\n        const uidEventList = Object.keys(events);\n\n        for (let i = 0, len = uidEventList.length; i < len; i++) {\n            const event = events[uidEventList[i]];\n\n            if (event.originalHandler === handler && event.delegationSelector === delegationSelector) {\n                return event\n            }\n        }\n\n        return null\n    }\n\n    function normalizeParams(originalTypeEvent, handler, delegationFn) {\n        const delegation = typeof handler === 'string';\n        const originalHandler = delegation ? delegationFn : handler;\n\n        let typeEvent = getTypeEvent(originalTypeEvent);\n        const isNative = nativeEvents.has(typeEvent);\n\n        if (!isNative) {\n            typeEvent = originalTypeEvent\n        }\n\n        return [delegation, originalHandler, typeEvent]\n    }\n\n    function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) {\n        if (typeof originalTypeEvent !== 'string' || !element) {\n            return\n        }\n\n        if (!handler) {\n            handler = delegationFn\n            delegationFn = null\n        }\n\n        // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position\n        // this prevents the handler from being dispatched the same way as mouseover or mouseout does\n        if (customEventsRegex.test(originalTypeEvent)) {\n            const wrapFn = fn => {\n                return function (event) {\n                    if (!event.relatedTarget || (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))) {\n                        return fn.call(this, event)\n                    }\n                }\n            };\n\n            if (delegationFn) {\n                delegationFn = wrapFn(delegationFn)\n            } else {\n                handler = wrapFn(handler)\n            }\n        }\n\n        const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn);\n        const events = getEvent(element);\n        const handlers = events[typeEvent] || (events[typeEvent] = {});\n        const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null);\n\n        if (previousFn) {\n            previousFn.oneOff = previousFn.oneOff && oneOff\n\n            return\n        }\n\n        const uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, ''));\n        const fn = delegation ?\n            bootstrapDelegationHandler(element, handler, delegationFn) :\n            bootstrapHandler(element, handler);\n\n        fn.delegationSelector = delegation ? handler : null\n        fn.originalHandler = originalHandler\n        fn.oneOff = oneOff\n        fn.uidEvent = uid\n        handlers[uid] = fn\n\n        element.addEventListener(typeEvent, fn, delegation)\n    }\n\n    function removeHandler(element, events, typeEvent, handler, delegationSelector) {\n        const fn = findHandler(events[typeEvent], handler, delegationSelector);\n\n        if (!fn) {\n            return\n        }\n\n        element.removeEventListener(typeEvent, fn, Boolean(delegationSelector))\n        delete events[typeEvent][fn.uidEvent]\n    }\n\n    function removeNamespacedHandlers(element, events, typeEvent, namespace) {\n        const storeElementEvent = events[typeEvent] || {};\n\n        Object.keys(storeElementEvent).forEach(handlerKey => {\n            if (handlerKey.includes(namespace)) {\n                const event = storeElementEvent[handlerKey];\n\n                removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector)\n            }\n        })\n    }\n\n    function getTypeEvent(event) {\n        // allow to get the native events from namespaced events ('click.bs.button' --> 'click')\n        event = event.replace(stripNameRegex, '')\n        return customEvents[event] || event\n    }\n\n    return {\n        on: function(element, event, handler, delegationFn) {\n            addHandler(element, event, handler, delegationFn, false)\n        },\n\n        one: function(element, event, handler, delegationFn) {\n            addHandler(element, event, handler, delegationFn, true)\n        },\n\n        off: function(element, originalTypeEvent, handler, delegationFn) {\n            if (typeof originalTypeEvent !== 'string' || !element) {\n                return\n            }\n\n            const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn);\n            const inNamespace = typeEvent !== originalTypeEvent;\n            const events = getEvent(element);\n            const isNamespace = originalTypeEvent.startsWith('.');\n\n            if (typeof originalHandler !== 'undefined') {\n                // Simplest case: handler is passed, remove that listener ONLY.\n                if (!events || !events[typeEvent]) {\n                    return\n                }\n\n                removeHandler(element, events, typeEvent, originalHandler, delegation ? handler : null)\n                return\n            }\n\n            if (isNamespace) {\n                Object.keys(events).forEach(elementEvent => {\n                    removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1))\n                })\n            }\n\n            const storeElementEvent = events[typeEvent] || {};\n            Object.keys(storeElementEvent).forEach(keyHandlers => {\n                const handlerKey = keyHandlers.replace(stripUidRegex, '');\n\n                if (!inNamespace || originalTypeEvent.includes(handlerKey)) {\n                    const event = storeElementEvent[keyHandlers];\n\n                    removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector)\n                }\n            })\n        },\n\n        trigger: function(element, event, args) {\n            if (typeof event !== 'string' || !element) {\n                return null\n            }\n\n            const $ = getjQuery();\n            const typeEvent = getTypeEvent(event);\n            const inNamespace = event !== typeEvent;\n            const isNative = nativeEvents.has(typeEvent);\n\n            let jQueryEvent;\n            let bubbles = true;\n            let nativeDispatch = true;\n            let defaultPrevented = false;\n            let evt = null;\n\n            if (inNamespace && $) {\n                jQueryEvent = $.Event(event, args)\n\n                $(element).trigger(jQueryEvent)\n                bubbles = !jQueryEvent.isPropagationStopped()\n                nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()\n                defaultPrevented = jQueryEvent.isDefaultPrevented()\n            }\n\n            if (isNative) {\n                evt = document.createEvent('HTMLEvents')\n                evt.initEvent(typeEvent, bubbles, true)\n            } else {\n                evt = new CustomEvent(event, {\n                    bubbles,\n                    cancelable: true\n                })\n            }\n\n            // merge custom information in our event\n            if (typeof args !== 'undefined') {\n                Object.keys(args).forEach(key => {\n                    Object.defineProperty(evt, key, {\n                        get() {\n                            return args[key]\n                        }\n                    })\n                })\n            }\n\n            if (defaultPrevented) {\n                evt.preventDefault()\n            }\n\n            if (nativeDispatch) {\n                element.dispatchEvent(evt)\n            }\n\n            if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') {\n                jQueryEvent.preventDefault()\n            }\n\n            return evt\n        }\n    }\n});\n","jquery/bootstrap/dom/selector-engine.js":"/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): dom/selector-engine.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\ndefine([\n    \"../util/index\"\n], function(Util) {\n    'use strict';\n\n    const isDisabled = Util.isDisabled;\n    const isVisible = Util.isVisible;\n\n    /**\n     * ------------------------------------------------------------------------\n     * Constants\n     * ------------------------------------------------------------------------\n     */\n\n    const NODE_TEXT = 3;\n\n    return {\n        find: function(selector, element = document.documentElement) {\n            return [].concat(...Element.prototype.querySelectorAll.call(element, selector))\n        },\n\n        findOne: function(selector, element = document.documentElement) {\n            return Element.prototype.querySelector.call(element, selector)\n        },\n\n        children: function(element, selector) {\n            return [].concat(...element.children)\n                .filter(child => child.matches(selector))\n        },\n\n        parents: function(element, selector) {\n            const parents = [];\n\n            let ancestor = element.parentNode;\n\n            while (ancestor && ancestor.nodeType === Node.ELEMENT_NODE && ancestor.nodeType !== NODE_TEXT) {\n                if (ancestor.matches(selector)) {\n                    parents.push(ancestor)\n                }\n\n                ancestor = ancestor.parentNode\n            }\n\n            return parents\n        },\n\n        prev: function(element, selector) {\n            let previous = element.previousElementSibling;\n\n            while (previous) {\n                if (previous.matches(selector)) {\n                    return [previous]\n                }\n\n                previous = previous.previousElementSibling\n            }\n\n            return []\n        },\n\n        next: function(element, selector) {\n            let next = element.nextElementSibling;\n\n            while (next) {\n                if (next.matches(selector)) {\n                    return [next]\n                }\n\n                next = next.nextElementSibling\n            }\n\n            return []\n        },\n\n        focusableChildren: function(element) {\n            const focusables = [\n                'a',\n                'button',\n                'input',\n                'textarea',\n                'select',\n                'details',\n                '[tabindex]',\n                '[contenteditable=\"true\"]'\n            ].map(selector => `${selector}:not([tabindex^=\"-\"])`).join(', ');\n\n            return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el))\n        }\n    }\n});\n","jquery/bootstrap/dom/manipulator.js":"/**\n * --------------------------------------------------------------------------\n * Bootstrap (v5.1.3): dom/manipulator.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\ndefine([], function() {\n    'use strict';\n\n    function normalizeData(val) {\n        if (val === 'true') {\n            return true\n        }\n\n        if (val === 'false') {\n            return false\n        }\n\n        if (val === Number(val).toString()) {\n            return Number(val)\n        }\n\n        if (val === '' || val === 'null') {\n            return null\n        }\n\n        return val\n    }\n\n    function normalizeDataKey(key) {\n        return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`)\n    }\n\n    return {\n        setDataAttribute: function(element, key, value) {\n            element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value)\n        },\n\n        removeDataAttribute: function(element, key) {\n            element.removeAttribute(`data-bs-${normalizeDataKey(key)}`)\n        },\n\n        getDataAttributes: function(element) {\n            if (!element) {\n                return {}\n            }\n\n            const attributes = {};\n\n            Object.keys(element.dataset)\n                .filter(key => key.startsWith('bs'))\n                .forEach(key => {\n                    let pureKey = key.replace(/^bs/, '');\n                    pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length)\n                    attributes[pureKey] = normalizeData(element.dataset[key])\n                })\n\n            return attributes\n        },\n\n        getDataAttribute: function(element, key) {\n            return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`))\n        },\n\n        offset: function(element) {\n            const rect = element.getBoundingClientRect();\n\n            return {\n                top: rect.top + window.pageYOffset,\n                left: rect.left + window.pageXOffset\n            }\n        },\n\n        position: function(element) {\n            return {\n                top: element.offsetTop,\n                left: element.offsetLeft\n            }\n        }\n    }\n});\n","Magento_GroupedProduct/js/product-ids-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_Catalog/js/product/view/product-ids',\n    'Magento_Catalog/js/product/view/product-info'\n], function ($, productIds, productInfo) {\n    'use strict';\n\n    /**\n     * Returns id's of products in form.\n     *\n     * @param {Object} config\n     * @param {HTMLElement} element\n     * @return {Array}\n     */\n    return function (config, element) {\n        $(element).find('div[data-product-id]').each(function () {\n            productIds.push($(this).data('productId').toString());\n            productInfo.push(\n                {\n                    'id': $(this).data('productId').toString()\n                }\n            );\n        });\n\n        return productIds();\n    };\n});\n","Magento_GroupedProduct/js/grouped-product.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'underscore',\n    'jquery-ui-modules/widget',\n    'jquery/jquery.parsequery'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.groupedProduct', {\n        options: {\n            qtySelector: 'input.qty',\n            qtyNameSelector: 'super_group'\n        },\n\n        /**\n         * Creates widget\n         * @private\n         */\n        _create: function () {\n            // Override defaults with URL query parameters and/or inputs values\n            this._overrideDefaults();\n        },\n\n        /**\n         * Override default options values settings with either URL query parameters or\n         * initialized inputs values.\n         * @private\n         */\n        _overrideDefaults: function () {\n            var hashIndex = window.location.href.indexOf('#');\n\n            if (hashIndex !== -1) {\n                this._parseQueryParams(window.location.href.substr(hashIndex + 1));\n            }\n        },\n\n        /**\n         * Parse query parameters from a query string and set options values based on the\n         * key value pairs of the parameters.\n         * @param {*} queryString - URL query string containing query parameters.\n         * @private\n         */\n        _parseQueryParams: function (queryString) {\n            var queryParams = $.parseQuery({\n                    query: queryString\n                }),\n                form = this.element,\n                qtyNameSelector = this.options.qtyNameSelector,\n                qtys = $(this.options.qtySelector, form);\n\n            $.each(queryParams, $.proxy(function (key, value) {\n                qtys.each(function (index, qty) {\n                    var nameSelector = qtyNameSelector.concat('[', key, ']');\n\n                    if (qty.name === nameSelector) {\n                        $(qty).val(value);\n                    }\n                });\n            }, this));\n        }\n    });\n\n    return $.mage.groupedProduct;\n});\n","Magento_GoogleAnalytics/js/google-analytics.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* jscs:disable */\n/* eslint-disable */\ndefine([\n    'jquery',\n    'mage/cookies'\n], function ($) {\n    'use strict';\n\n    /**\n     * @param {Object} config\n     */\n    return function (config) {\n        var allowServices = false,\n            allowedCookies,\n            allowedWebsites;\n\n        if (config.isCookieRestrictionModeEnabled) {\n            allowedCookies = $.mage.cookies.get(config.cookieName);\n\n            if (allowedCookies !== null) {\n                allowedWebsites = JSON.parse(allowedCookies);\n\n                if (allowedWebsites[config.currentWebsite] === 1) {\n                    allowServices = true;\n                }\n            }\n        } else {\n            allowServices = true;\n        }\n\n        if (allowServices) {\n            (function (i, s, o, g, r, a, m) {\n                i.GoogleAnalyticsObject = r;\n                i[r] = i[r] || function () {\n                        (i[r].q = i[r].q || []).push(arguments)\n                    }, i[r].l = 1 * new Date();\n                a = s.createElement(o),\n                    m = s.getElementsByTagName(o)[0];\n                a.async = 1;\n                a.src = g;\n                m.parentNode.insertBefore(a, m)\n            })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');\n\n            // Process page info\n            ga('create', config.pageTrackingData.accountId, 'auto');\n\n            if (config.pageTrackingData.isAnonymizedIpActive) {\n                ga('set', 'anonymizeIp', true);\n            }\n\n            // Process orders data\n            if (config.ordersTrackingData.hasOwnProperty('currency')) {\n                ga('require', 'ec', 'ec.js');\n\n                ga('set', 'currencyCode', config.ordersTrackingData.currency);\n\n                // Collect product data for GA\n                if (config.ordersTrackingData.products) {\n                    $.each(config.ordersTrackingData.products, function (index, value) {\n                        ga('ec:addProduct', value);\n                    });\n                }\n\n                // Collect orders data for GA\n                if (config.ordersTrackingData.orders) {\n                    $.each(config.ordersTrackingData.orders, function (index, value) {\n                        ga('ec:setAction', 'purchase', value);\n                    });\n                }\n\n                ga('send', 'pageview');\n            } else {\n                // Process Data if not orders\n                ga('send', 'pageview' + config.pageTrackingData.optPageUrl);\n            }\n        }\n    }\n});\n","Magento_PaypalCaptcha/js/view/payment/list-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Captcha/js/model/captchaList'\n], function ($, captchaList) {\n    'use strict';\n\n    var mixin = {\n\n        formId: 'co-payment-form',\n\n        /**\n         * Sets custom template for Payflow Pro\n         *\n         * @param {Object} payment\n         * @returns {Object}\n         */\n        createComponent: function (payment) {\n\n            var component = this._super(payment);\n\n            if (component.component === 'Magento_Paypal/js/view/payment/method-renderer/payflowpro-method') {\n                component.template = 'Magento_PaypalCaptcha/payment/payflowpro-form';\n                $(window).off('clearTimeout')\n                    .on('clearTimeout', this.clearTimeout.bind(this));\n            }\n\n            return component;\n        },\n\n        /**\n         * Overrides default window.clearTimeout() to catch errors from iframe and reload Captcha.\n         *\n         * @param {Number} timeoutID\n         */\n        clearTimeout: function (timeoutID) {\n            var captcha = captchaList.getCaptchaByFormId(this.formId);\n\n            if (captcha !== null) {\n                captcha.refresh();\n            }\n            clearTimeout(timeoutID);\n        }\n    };\n\n    /**\n     * Overrides `Magento_Checkout/js/view/payment/list::createComponent`\n     */\n    return function (target) {\n        return target.extend(mixin);\n    };\n});\n","Magento_PaypalCaptcha/js/view/payment/method-renderer/payflowpro-method-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_PaypalCaptcha/js/model/skipRefreshCaptcha'\n], function (skipRefreshCaptcha) {\n    'use strict';\n\n    var payflowProMethodMixin = {\n        /**\n         * @override\n         */\n        placeOrder: function () {\n            skipRefreshCaptcha.skip(true);\n            this._super();\n        }\n    };\n\n    return function (payflowProMethod) {\n        return payflowProMethod.extend(payflowProMethodMixin);\n    };\n});\n","Magento_PaypalCaptcha/js/view/checkout/paymentCaptcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Captcha/js/view/checkout/defaultCaptcha',\n    'Magento_Captcha/js/model/captchaList',\n    'Magento_Captcha/js/model/captcha'\n],\nfunction ($, defaultCaptcha, captchaList, Captcha) {\n    'use strict';\n\n    return defaultCaptcha.extend({\n\n        /** @inheritdoc */\n        initialize: function () {\n            var captchaConfigPayment,\n                currentCaptcha;\n\n            this._super();\n\n            if (window[this.configSource] && window[this.configSource].captchaPayments) {\n                captchaConfigPayment = window[this.configSource].captchaPayments;\n\n                $.each(captchaConfigPayment, function (formId, captchaData) {\n                    var captcha;\n\n                    captchaData.formId = formId;\n                    captcha = Captcha(captchaData);\n                    captchaList.add(captcha);\n                });\n            }\n\n            currentCaptcha = captchaList.getCaptchaByFormId(this.formId);\n\n            if (currentCaptcha != null) {\n                currentCaptcha.setIsVisible(true);\n                this.setCurrentCaptcha(currentCaptcha);\n            }\n        }\n    });\n});\n","Magento_PaypalCaptcha/js/view/checkout/defaultCaptcha-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_PaypalCaptcha/js/model/skipRefreshCaptcha'\n], function (skipRefreshCaptcha) {\n    'use strict';\n\n    var defaultCaptchaMixin = {\n        /**\n         * @override\n         */\n        refresh: function () {\n            if (!skipRefreshCaptcha.skip()) {\n                this._super();\n            } else {\n                skipRefreshCaptcha.skip(false);\n            }\n        }\n    };\n\n    return function (defaultCaptcha) {\n        return defaultCaptcha.extend(defaultCaptchaMixin);\n    };\n});\n","Magento_PaypalCaptcha/js/model/skipRefreshCaptcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['ko'], function (ko) {\n    'use strict';\n\n    return {\n        skip: ko.observable(false)\n    };\n});\n","js/navigation-menu.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @deprecated\n * @see lib/web/mage/menu.js\n */\ndefine([\n    'jquery',\n    'matchMedia',\n    'mage/template',\n    'mage/dropdowns',\n    'mage/terms'\n], function ($, mediaCheck, mageTemplate) {\n    'use strict';\n\n    $.widget('mage.navigationMenu', {\n        options: {\n            itemsContainer: '> ul',\n            topLevel: 'li.level0',\n            topLevelSubmenu: '> .submenu',\n            topLevelHoverClass: 'hover',\n            expandedTopLevel: '.more',\n            hoverInTimeout: 300,\n            hoverOutTimeout: 500,\n            submenuAnimationSpeed: 200,\n            collapsable: true,\n            collapsableDropdownTemplate:\n                '<script type=\"text/x-magento-template\">' +\n                    '<li class=\"level0 level-top more parent\">' +\n                        '<div class=\"submenu\">' +\n                            '<ul><%= elems %></ul>' +\n                        '</div>' +\n                    '</li>' +\n                '</script>'\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            this.itemsContainer = $(this.options.itemsContainer, this.element);\n            this.topLevel = $(this.options.topLevel, this.element);\n            this.topLevelSubmenu = $(this.options.topLevelSubmenu, this.topLevel);\n\n            this._bind();\n        },\n\n        /**\n         * @private\n         */\n        _init: function () {\n            if (this.options.collapsable) {\n                setTimeout($.proxy(function () {\n                    this._checkToCollapseOrExpand();\n                }, this), 100);\n            }\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            this._on({\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                'mouseenter > ul > li.level0': function (e) {\n                    if (!this.entered) { // fix IE bug with 'mouseenter' event\n                        this.timeoutId && clearTimeout(this.timeoutId);\n                        this.timeoutId = setTimeout($.proxy(function () {\n                            this._openSubmenu(e);\n                        }, this), this.options.hoverInTimeout);\n                        this.entered = true;\n                    }\n                },\n\n                /**\n                 * @param {jQuery.Event} e\n                 */\n                'mouseleave > ul > li.level0': function (e) {\n                    this.entered = null;\n\n                    this.timeoutId && clearTimeout(this.timeoutId);\n                    this.timeoutId = setTimeout($.proxy(function () {\n                        this._closeSubmenu(e.currentTarget);\n                    }, this), this.options.hoverOutTimeout);\n                },\n\n                /**\n                 * @param {jQuert.Event} e\n                 */\n                'click': function (e) {\n                    e.stopPropagation();\n                }\n            });\n\n            $(document)\n                .on('click.hideMenu', $.proxy(function () {\n                    var isOpened = this.topLevel.filter(function () {\n                        return $(this).data('opened');\n                    });\n\n                    if (isOpened) {\n                        this._closeSubmenu(null, false);\n                    }\n                }, this));\n\n            $(window)\n                .on('resize', $.proxy(function () {\n                    this.timeoutOnResize && clearTimeout(this.timeoutOnResize);\n                    this.timeoutOnResize = setTimeout($.proxy(function () {\n                        if (this.options.collapsable) {\n                            if ($(this.options.expandedTopLevel, this.element).length) {\n                                this._expandMenu();\n                            }\n                            this._checkToCollapseOrExpand();\n                        }\n                    }, this), 300);\n                }, this));\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @private\n         */\n        _openSubmenu: function (e) {\n            var menuItem = e.currentTarget;\n\n            if (!$(menuItem).data('opened')) {\n                this._closeSubmenu(menuItem, true, true);\n\n                $(this.options.topLevelSubmenu, menuItem)\n                    .slideDown(this.options.submenuAnimationSpeed, $.proxy(function () {\n                        $(menuItem).addClass(this.options.topLevelHoverClass);\n                        $(menuItem).data('opened', true);\n                    }, this));\n            } else if ($(e.target).closest(this.options.topLevel)) {\n                $(e.target)\n                    .addClass(this.options.topLevelHoverClass)\n                    .siblings(this.options.topLevel)\n                        .removeClass(this.options.topLevelHoverClass);\n            }\n        },\n\n        /**\n         * @param {*} menuItem\n         * @param {*} excludeCurrent\n         * @param {*} fast\n         * @private\n         */\n        _closeSubmenu: function (menuItem, excludeCurrent, fast) {\n            var topLevel = $(this.options.topLevel, this.element),\n                activeSubmenu = $(this.options.topLevelSubmenu, menuItem || null);\n\n            $(this.options.topLevelSubmenu, topLevel)\n                .filter(function () {\n                    return excludeCurrent ? $(this).not(activeSubmenu) : true;\n                })\n                .slideUp(fast ? 0 : this.options.submenuAnimationSpeed);\n\n            topLevel\n                .removeClass(this.options.topLevelHoverClass)\n                .data('opened', false);\n        },\n\n        /**\n         * @private\n         */\n        _checkToCollapseOrExpand: function () {\n            var navWidth, totalWidth, startCollapseIndex;\n\n            if ($('html').hasClass('lt-640') || $('html').hasClass('w-640')) {\n                return;\n            }\n\n            navWidth = this.itemsContainer.width();\n            totalWidth = 0;\n            startCollapseIndex = 0;\n\n            $.each($(this.options.topLevel, this.element), function (index, item) {\n                totalWidth += $(item).outerWidth(true);\n\n                if (totalWidth > navWidth && !startCollapseIndex) {\n                    startCollapseIndex = index - 2;\n                }\n            });\n\n            this[startCollapseIndex ? '_collapseMenu' : '_expandMenu'](startCollapseIndex);\n        },\n\n        /**\n         * @param {*} startCollapseIndex\n         * @private\n         */\n        _collapseMenu: function (startCollapseIndex) {\n            this.elemsToCollapse = this.topLevel.filter(function (index) {\n                return index > startCollapseIndex;\n            });\n            this.elemsToCollapseClone = $('<div></div>').append(this.elemsToCollapse.clone()).html();\n\n            this.collapsableDropdown = $(\n                mageTemplate(\n                    this.options.collapsableDropdownTemplate,\n                    {\n                        elems: this.elemsToCollapseClone\n                    }\n                )\n            );\n\n            this.itemsContainer.append(this.collapsableDropdown);\n            this.elemsToCollapse.detach();\n        },\n\n        /**\n         * @private\n         */\n        _expandMenu: function () {\n            this.elemsToCollapse && this.elemsToCollapse.appendTo(this.itemsContainer);\n            this.collapsableDropdown && this.collapsableDropdown.remove();\n        },\n\n        /**\n         * @private\n         */\n        _destroy: function () {\n            this._expandMenu();\n        }\n    });\n\n    /*\n     * Provides \"Continium\" effect for submenu\n     * */\n    $.widget('mage.navigationMenu', $.mage.navigationMenu, {\n        options: {\n            parentLevel: '> ul > li.level0',\n            submenuAnimationSpeed: 150,\n            submenuContiniumEffect: false\n        },\n\n        /**\n         * @private\n         */\n        _init: function () {\n            this._super();\n            this._applySubmenuStyles();\n        },\n\n        /**\n         * @private\n         */\n        _applySubmenuStyles: function () {\n            $(this.options.topLevelSubmenu, $(this.options.topLevel, this.element))\n                .removeAttr('style');\n\n            $(this.options.topLevelSubmenu, $(this.options.parentLevel, this.element))\n                .css({\n                    display: 'block',\n                    height: 0,\n                    overflow: 'hidden'\n                });\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @private\n         */\n        _openSubmenu: function (e) {\n            var menuItem = e.currentTarget,\n                submenu = $(this.options.topLevelSubmenu, menuItem),\n                openedItems = $(this.options.topLevel, this.element).filter(function () {\n                    return $(this).data('opened');\n                });\n\n            if (submenu.length) {\n                this.heightToAnimate = $(this.options.itemsContainer, submenu).outerHeight(true);\n\n                if (openedItems.length) {\n                    this._closeSubmenu(menuItem, true, this.heightToAnimate, $.proxy(function () {\n                        submenu.css({\n                            height: 'auto'\n                        });\n                        $(menuItem)\n                            .addClass(this.options.topLevelHoverClass);\n                    }, this), e);\n                } else {\n                    submenu.animate({\n                        height: this.heightToAnimate\n                    }, this.options.submenuAnimationSpeed, $.proxy(function () {\n                        $(menuItem)\n                            .addClass(this.options.topLevelHoverClass);\n                    }, this));\n                }\n\n                $(menuItem)\n                    .data('opened', true);\n            } else {\n                this._closeSubmenu(menuItem);\n            }\n        },\n\n        /**\n         * @param {*} menuItem\n         * @param {*} excludeCurrent\n         * @param {*} heightToAnimate\n         * @param {Function} callback\n         * @private\n         */\n        _closeSubmenu: function (menuItem, excludeCurrent, heightToAnimate, callback) {\n            var topLevel = $(this.options.topLevel, this.itemsContainer),\n                prevOpenedItem, prevOpenedSubmenu;\n\n            if (!excludeCurrent) {\n                $(this.options.topLevelSubmenu, $(this.options.parentLevel, this.element))\n                    .animate({\n                        height: 0\n                    });\n\n                topLevel\n                    .data('opened', false)\n                    .removeClass(this.options.topLevelHoverClass);\n            } else {\n                prevOpenedItem = topLevel.filter(function () {\n                    return $(this).data('opened');\n                });\n                prevOpenedSubmenu = $(this.options.topLevelSubmenu, prevOpenedItem);\n\n                prevOpenedSubmenu.animate({\n                    height: heightToAnimate\n                }, this.options.submenuAnimationSpeed, 'linear', function () {\n                    $(this).css({\n                        height: 0\n                    });\n                    callback && callback();\n                });\n\n                prevOpenedItem\n                    .data('opened', false)\n                    .removeClass(this.options.topLevelHoverClass);\n            }\n        },\n\n        /**\n         * @private\n         */\n        _collapseMenu: function () {\n            this._superApply(arguments);\n            this._applySubmenuStyles();\n        }\n    });\n\n    //  Responsive menu\n    $.widget('mage.navigationMenu', $.mage.navigationMenu, {\n        options: {\n            responsive: false,\n            origNavPlaceholder: '.page-header',\n            mainContainer: 'body',\n            pageWrapper: '.page-wrapper',\n            openedMenuClass: 'opened',\n            toggleActionPlaceholder: '.block-search',\n            itemWithSubmenu: 'li.parent',\n            titleWithSubmenu: 'li.parent > a',\n            submenu: 'li.parent > .submenu',\n            toggleActionTemplate:\n                '<script type=\"text/x-magento-template\">' +\n                    '<span data-action=\"toggle-nav\" class=\"action toggle nav\">Toggle Nav</span>' +\n                '</script>',\n            submenuActionsTemplate:\n                '<script type=\"text/x-magento-template\">' +\n                    '<li class=\"action all\">' +\n                        '<a href=\"<%= categoryURL %>\"><span>All <%= category %></span></a>' +\n                    '</li>' +\n                '</script>',\n            navigationSectionsWrapperTemplate:\n                '<script type=\"text/x-magento-template\">' +\n                    '<dl class=\"navigation-tabs\" data-sections=\"tabs\">' +\n                    '</dl>' +\n                '</script>',\n            navigationItemWrapperTemplate:\n                '<script type=\"text/x-magento-template\">' +\n                    '<dt class=\"item title <% if (active) { %>active<% } %>\" data-section=\"title\">' +\n                        '<a class=\"switch\" data-toggle=\"switch\" href=\"#TODO\"><%= title %></a>' +\n                    '</dt>' +\n                    '<dd class=\"item content <% if (active) { %>active<%}%>\" data-section=\"content\">' +\n                    '</dd>' +\n                '</script>'\n        },\n\n        /**\n         * @private\n         */\n        _init: function () {\n            this._super();\n\n            this.mainContainer = $(this.options.mainContainer);\n            this.pageWrapper = $(this.options.pageWrapper);\n            this.toggleAction = $(mageTemplate(this.options.toggleActionTemplate, {}));\n\n            if (this.options.responsive) {\n                mediaCheck({\n                    media: '(min-width: 768px)',\n                    entry: $.proxy(function () {\n                        this._toggleDesktopMode();\n                    }, this),\n                    exit: $.proxy(function () {\n                        this._toggleMobileMode();\n                    }, this)\n                });\n            }\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            this._super();\n            this._bindDocumentEvents();\n        },\n\n        /**\n         * @private\n         */\n        _bindDocumentEvents: function () {\n            if (!this.eventsBound) {\n                $(document)\n                    .on('click.toggleMenu', '.action.toggle.nav', $.proxy(function (e) {\n                        if ($(this.element).data('opened')) {\n                            this._hideMenu();\n                        } else {\n                            this._showMenu();\n                        }\n                        e.stopPropagation();\n                        this.mobileNav.scrollTop(0);\n                        this._fixedBackLink();\n                    }, this))\n                    .on('click.hideMenu', this.options.pageWrapper, $.proxy(function () {\n                        if ($(this.element).data('opened')) {\n                            this._hideMenu();\n                            this.mobileNav.scrollTop(0);\n                            this._fixedBackLink();\n                        }\n                    }, this))\n                    .on('click.showSubmenu', this.options.titleWithSubmenu, $.proxy(function (e) {\n                        this._showSubmenu(e);\n\n                        e.preventDefault();\n                        this.mobileNav.scrollTop(0);\n                        this._fixedBackLink();\n                    }, this))\n                    .on('click.hideSubmenu', '.action.back', $.proxy(function (e) {\n                        this._hideSubmenu(e);\n                        this.mobileNav.scrollTop(0);\n                        this._fixedBackLink();\n                    }, this));\n\n                this.eventsBound = true;\n            }\n        },\n\n        /**\n         * @private\n         */\n        _showMenu: function () {\n            $(this.element).data('opened', true);\n            this.mainContainer.add('html').addClass(this.options.openedMenuClass);\n        },\n\n        /**\n         * @private\n         */\n        _hideMenu: function () {\n            $(this.element).data('opened', false);\n            this.mainContainer.add('html').removeClass(this.options.openedMenuClass);\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @private\n         */\n        _showSubmenu: function (e) {\n            var submenu;\n\n            $(e.currentTarget).addClass('action back');\n            submenu = $(e.currentTarget).siblings('.submenu');\n\n            submenu.addClass('opened');\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @private\n         */\n        _hideSubmenu: function (e) {\n            var submenuSelector = '.submenu',\n                submenu = $(e.currentTarget).next(submenuSelector);\n\n            $(e.currentTarget).removeClass('action back');\n            submenu.removeClass('opened');\n        },\n\n        /**\n         * @private\n         */\n        _renderSubmenuActions: function () {\n            $.each(\n                $(this.options.itemWithSubmenu),\n                $.proxy(function (index, item) {\n                    var actions = $(mageTemplate(\n                            this.options.submenuActionsTemplate,\n                            {\n                                category: $('> a > span', item).text(),\n                                categoryURL: $('> a', item).attr('href')\n                            }\n                        )),\n                        submenu = $('> .submenu', item),\n                        items = $('> ul', submenu);\n\n                    items.prepend(actions);\n                }, this)\n            );\n        },\n\n        /**\n         * @private\n         */\n        _toggleMobileMode: function () {\n            this._expandMenu();\n\n            $(this.options.topLevelSubmenu, $(this.options.topLevel, this.element))\n                .removeAttr('style');\n\n            this.toggleAction.insertBefore(this.options.toggleActionPlaceholder);\n            this.mobileNav = $(this.element).detach().clone();\n            this.mainContainer.prepend(this.mobileNav);\n            this.mobileNav.find('> ul').addClass('nav');\n            this._insertExtraItems();\n            this._wrapItemsInSections();\n            this.mobileNav.scroll($.proxy(function () {\n                this._fixedBackLink();\n            }, this));\n\n            this._renderSubmenuActions();\n            this._bindDocumentEvents();\n        },\n\n        /**\n         * @private\n         */\n        _toggleDesktopMode: function () {\n            this.mobileNav && this.mobileNav.remove();\n            this.toggleAction.detach();\n            $(this.element).insertAfter(this.options.origNavPlaceholder);\n\n            $(document)\n                .off('click.toggleMenu', '.action.toggle.nav')\n                .off('click.hideMenu', this.options.pageWrapper)\n                .off('click.showSubmenu', this.options.titleWithSubmenu)\n                .off('click.hideSubmenu', '.action.back');\n\n            this.eventsBound = false;\n\n            this._applySubmenuStyles();\n        },\n\n        /**\n         * @private\n         */\n        _insertExtraItems: function () {\n            var settings, footerSettings, account;\n\n            if ($('.header.panel .switcher').length) {\n                settings = $('.header.panel .switcher')\n                    .clone()\n                    .addClass('settings');\n\n                this.mobileNav.prepend(settings);\n            }\n\n            if ($('.footer .switcher').length) {\n                footerSettings = $('.footer .switcher')\n                    .clone()\n                    .addClass('settings');\n\n                this.mobileNav.prepend(footerSettings);\n            }\n\n            if ($('.header.panel .header.links li').length) {\n                account = $('.header.panel > .header.links')\n                    .clone()\n                    .addClass('account');\n\n                this.mobileNav.prepend(account);\n            }\n        },\n\n        /**\n         * @private\n         */\n        _wrapItemsInSections: function () {\n            var account = $('> .account', this.mobileNav),\n                settings = $('> .settings', this.mobileNav),\n                nav = $('> .nav', this.mobileNav),\n                navigationSectionsWrapper = $(mageTemplate(this.options.navigationSectionsWrapperTemplate, {})),\n                navigationItemWrapper;\n\n            this.mobileNav.append(navigationSectionsWrapper);\n\n            if (nav.length) {\n                navigationItemWrapper = $(mageTemplate(this.options.navigationItemWrapperTemplate, {\n                    title: 'Menu'\n                }));\n                navigationSectionsWrapper.append(navigationItemWrapper);\n                navigationItemWrapper.eq(1).append(nav);\n            }\n\n            if (account.length) {\n                navigationItemWrapper = $(mageTemplate(this.options.navigationItemWrapperTemplate, {\n                    title: 'Account'\n                }));\n                navigationSectionsWrapper.append(navigationItemWrapper);\n                navigationItemWrapper.eq(1).append(account);\n            }\n\n            if (settings.length) {\n                navigationItemWrapper = $(\n                    mageTemplate(this.options.navigationItemWrapperTemplate, {\n                        title: 'Settings'\n                    })\n                );\n                navigationSectionsWrapper.append(navigationItemWrapper);\n                navigationItemWrapper.eq(1).append(settings);\n            }\n\n            navigationSectionsWrapper.addClass(\n                'navigation-tabs-' + navigationSectionsWrapper.find('[data-section=\"title\"]').length\n            );\n            navigationSectionsWrapper.terms();\n        },\n\n        /**\n         * @private\n         */\n        _fixedBackLink: function () {\n            var linksBack = this.mobileNav.find('.submenu .action.back'),\n                linkBack = this.mobileNav.find('.submenu.opened > ul > .action.back').last(),\n                subMenu, navOffset, linkBackHeight;\n\n            linksBack.removeClass('fixed');\n\n            if (linkBack.length) {\n                subMenu = linkBack.parent();\n                navOffset = this.mobileNav.find('.nav').position().top;\n                linkBackHeight = linkBack.height();\n\n                if (navOffset <= 0) {\n                    linkBack.addClass('fixed');\n                    subMenu.css({\n                        paddingTop: linkBackHeight\n                    });\n                } else {\n                    linkBack.removeClass('fixed');\n                    subMenu.css({\n                        paddingTop: 0\n                    });\n                }\n            }\n        }\n    });\n\n    return $.mage.navigationMenu;\n});\n","magnifier/magnifier.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n(function ($) {\n    $.fn.magnify = function (options) {\n        'use strict';\n\n        var magnify = new Magnify($(this), options);\n\n        /* events must be tracked here */\n\n        /**\n         * Return that from _init function\n         *\n         */\n        return magnify;\n    };\n\n    function Magnify(element, options) {\n        var customUserOptions = options || {},\n            $box = $(element),\n            $thumb,\n            that = this,\n            largeWrapper = options.largeWrapper || '.magnifier-preview',\n            $magnifierPreview = $(largeWrapper);\n\n        curThumb = null,\n        magnifierOptions = {\n            x: 0,\n            y: 0,\n            w: 0,\n            h: 0,\n            lensW: 0,\n            lensH: 0,\n            lensBgX: 0,\n            lensBgY: 0,\n            largeW: 0,\n            largeH: 0,\n            largeL: 0,\n            largeT: 0,\n            zoom: 2,\n            zoomMin: 1.1,\n            zoomMax: 5,\n            mode: 'outside',\n            eventType: 'click',\n            status: 0,\n            zoomAttached: false,\n            zoomable: customUserOptions.zoomable !== undefined ?\n                customUserOptions.zoomable\n                : false,\n            onthumbenter: customUserOptions.onthumbenter !== undefined ?\n                customUserOptions.onthumbenter\n                : null,\n            onthumbmove: customUserOptions.onthumbmove !== undefined ?\n                customUserOptions.onthumbmove\n                : null,\n            onthumbleave: customUserOptions.onthumbleave !== undefined ?\n                customUserOptions.onthumbleave\n                : null,\n            onzoom: customUserOptions.onzoom !== undefined ?\n                customUserOptions.onzoom\n                : null\n        },\n        pos = {\n            t: 0,\n            l: 0,\n            x: 0,\n            y: 0\n        },\n        gId = 0,\n        status = 0,\n        curIdx = '',\n        curLens = null,\n        curLarge = null,\n        lensbg = customUserOptions.bg !== undefined ?\n            customUserOptions.lensbg\n            : true,\n        gZoom = customUserOptions.zoom !== undefined ?\n            customUserOptions.zoom\n            : magnifierOptions.zoom,\n        gZoomMin = customUserOptions.zoomMin !== undefined ?\n            customUserOptions.zoomMin\n            : magnifierOptions.zoomMin,\n        gZoomMax = customUserOptions.zoomMax !== undefined ?\n            customUserOptions.zoomMax\n            : magnifierOptions.zoomMax,\n        gMode = customUserOptions.mode || magnifierOptions.mode,\n        gEventType = customUserOptions.eventType || magnifierOptions.eventType,\n        data = {},\n        inBounds = false,\n        isOverThumb = false,\n        rate = 1,\n        paddingX = 0,\n        paddingY = 0,\n        enabled = true,\n        showWrapper = true;\n\n        var MagnifyCls = {\n            magnifyHidden: 'magnify-hidden',\n            magnifyOpaque: 'magnify-opaque',\n            magnifyFull: 'magnify-fullimage'\n        };\n\n        /**\n         * Update Lens positon on.\n         *\n         */\n        that.update = function () {\n            updateLensOnLoad();\n        };\n\n        /**\n         * Init new Magnifier\n         *\n         */\n        that.init = function () {\n            _init($box, options);\n        };\n\n        function _toBoolean(str) {\n            if (typeof str === 'string') {\n                if (str === 'true') {\n                    return true;\n                } else if (str === 'false' || '') {\n                    return false;\n                }\n                console.warn('Wrong type: can\\'t be transformed to Boolean');\n\n            } else if (typeof str === 'boolean') {\n                return str;\n            }\n        }\n\n        function createLens(thumb) {\n            if ($(thumb).siblings('.magnify-lens').length) {\n                return false;\n            }\n            var lens = $('<div class=\"magnify-lens magnify-hidden\" data-gallery-role=\"magnifier-zoom\"></div>');\n\n            $(thumb).parent().append(lens);\n        }\n\n        function updateLensOnLoad(idSelectorMainImg, thumb, largeImgInMagnifyLens, largeWrapper) {\n            var magnifyLensElement= $box.find('.magnify-lens'),\n                textWrapper;\n\n            if (data[idSelectorMainImg].status === 1) {\n                textWrapper = $('<div class=\"magnifier-loader-text\"></div>');\n                magnifyLensElement.className = 'magnifier-loader magnify-hidden';\n                textWrapper.html('Loading...');\n                magnifyLensElement.html('').append(textWrapper);\n            } else if (data[idSelectorMainImg].status === 2) {\n                magnifyLensElement.addClass(MagnifyCls.magnifyHidden);\n                magnifyLensElement.html('');\n\n                largeImgInMagnifyLens.id = idSelectorMainImg + '-large';\n                largeImgInMagnifyLens.style.width = data[idSelectorMainImg].largeImgInMagnifyLensWidth + 'px';\n                largeImgInMagnifyLens.style.height = data[idSelectorMainImg].largeImgInMagnifyLensHeight + 'px';\n                largeImgInMagnifyLens.className = 'magnifier-large magnify-hidden';\n\n                if (data[idSelectorMainImg].mode === 'inside') {\n                    magnifyLensElement.append(largeImgInMagnifyLens);\n                } else {\n                    largeWrapper.html('').append(largeImgInMagnifyLens);\n                }\n            }\n\n            data[idSelectorMainImg].lensH = data[idSelectorMainImg].lensH > $thumb.height() ? $thumb.height() : data[idSelectorMainImg].lensH;\n\n            if (Math.round(data[idSelectorMainImg].lensW) === 0) {\n                magnifyLensElement.css('display', 'none');\n            } else {\n                magnifyLensElement.css({\n                    width: Math.round(data[idSelectorMainImg].lensW) + 'px',\n                    height: Math.round(data[idSelectorMainImg].lensH) + 'px',\n                    display: ''\n                });\n            }\n        }\n\n        function getMousePos() {\n            var xPos = pos.x - magnifierOptions.x,\n                yPos = pos.y - magnifierOptions.y,\n                t,\n                l;\n\n            inBounds =  xPos < 0 || yPos < 0 || xPos > magnifierOptions.w || yPos > magnifierOptions.h  ? false : true;\n\n            l = xPos - magnifierOptions.lensW / 2;\n            t = yPos - magnifierOptions.lensH / 2;\n\n            if (xPos < magnifierOptions.lensW / 2) {\n                l = 0;\n            }\n\n            if (yPos < magnifierOptions.lensH / 2) {\n                t = 0;\n            }\n\n            if (xPos - magnifierOptions.w + Math.ceil(magnifierOptions.lensW / 2) > 0) {\n                l = magnifierOptions.w - Math.ceil(magnifierOptions.lensW + 2);\n            }\n\n            if (yPos - magnifierOptions.h + Math.ceil(magnifierOptions.lensH / 2) > 0) {\n                t = magnifierOptions.h - Math.ceil(magnifierOptions.lensH);\n            }\n\n            pos.l = l;\n            pos.t = t;\n\n            magnifierOptions.lensBgX = pos.l;\n            magnifierOptions.lensBgY = pos.t;\n\n            if (magnifierOptions.mode === 'inside') {\n                magnifierOptions.largeL = Math.round(xPos * (magnifierOptions.zoom - magnifierOptions.lensW / magnifierOptions.w));\n                magnifierOptions.largeT = Math.round(yPos * (magnifierOptions.zoom - magnifierOptions.lensH / magnifierOptions.h));\n            } else {\n                magnifierOptions.largeL = Math.round(magnifierOptions.lensBgX * magnifierOptions.zoom * (magnifierOptions.largeWrapperW / magnifierOptions.w));\n                magnifierOptions.largeT = Math.round(magnifierOptions.lensBgY * magnifierOptions.zoom * (magnifierOptions.largeWrapperH / magnifierOptions.h));\n            }\n        }\n\n        function onThumbEnter() {\n            if (_toBoolean(enabled)) {\n                magnifierOptions = data[curIdx];\n                curLens = $box.find('.magnify-lens');\n\n                if (magnifierOptions.status === 2) {\n                    curLens.removeClass(MagnifyCls.magnifyOpaque);\n                    curLarge = $('#' + curIdx + '-large');\n                    curLarge.removeClass(MagnifyCls.magnifyHidden);\n                } else if (magnifierOptions.status === 1) {\n                    curLens.className = 'magnifier-loader';\n                }\n            }\n        }\n\n        function onThumbLeave() {\n            if (magnifierOptions.status > 0) {\n                var handler = magnifierOptions.onthumbleave;\n\n                if (handler !== null) {\n                    handler({\n                        thumb: curThumb,\n                        lens: curLens,\n                        large: curLarge,\n                        x: pos.x,\n                        y: pos.y\n                    });\n                }\n\n                if (!curLens.hasClass(MagnifyCls.magnifyHidden)) {\n                    curLens.addClass(MagnifyCls.magnifyHidden);\n\n                    //$curThumb.removeClass(MagnifyCls.magnifyOpaque);\n                    if (curLarge !== null) {\n                        curLarge.addClass(MagnifyCls.magnifyHidden);\n                    }\n                }\n            }\n        }\n\n        function move() {\n            if (_toBoolean(enabled)) {\n                if (status !== magnifierOptions.status) {\n                    onThumbEnter();\n                }\n\n                if (magnifierOptions.status > 0) {\n                    curThumb.className = magnifierOptions.thumbCssClass + ' magnify-opaque';\n\n                    if (magnifierOptions.status === 1) {\n                        curLens.className = 'magnifier-loader';\n                    } else if (magnifierOptions.status === 2) {\n                        curLens.removeClass(MagnifyCls.magnifyHidden);\n                        curLarge.removeClass(MagnifyCls.magnifyHidden);\n                        curLarge.css({\n                            left: '-' + magnifierOptions.largeL + 'px',\n                            top: '-' + magnifierOptions.largeT + 'px'\n                        });\n                    }\n\n                    var borderOffset = 2; // Offset for magnify-lens border\n                    pos.t = pos.t <= 0 ? 0 : pos.t - borderOffset;\n\n                    curLens.css({\n                        left: pos.l + paddingX + 'px',\n                        top: pos.t + paddingY + 'px'\n                    });\n\n                    if (lensbg) {\n                        curLens.css({\n                            'background-color': 'rgba(f,f,f,.5)'\n                        });\n                    } else {\n                        curLens.get(0).style.backgroundPosition = '-' +\n                        magnifierOptions.lensBgX + 'px -' +\n                        magnifierOptions.lensBgY + 'px';\n                    }\n                    var handler = magnifierOptions.onthumbmove;\n\n                    if (handler !== null) {\n                        handler({\n                            thumb: curThumb,\n                            lens: curLens,\n                            large: curLarge,\n                            x: pos.x,\n                            y: pos.y\n                        });\n                    }\n                }\n\n                status = magnifierOptions.status;\n            }\n        }\n\n        function setThumbData(mainImage, mainImageData) {\n            var thumbBounds = mainImage.getBoundingClientRect(),\n                w = 0,\n                h = 0;\n\n            mainImageData.x = Math.round(thumbBounds.left);\n            mainImageData.y = Math.round(thumbBounds.top);\n            mainImageData.w = Math.round(thumbBounds.right - mainImageData.x);\n            mainImageData.h = Math.round(thumbBounds.bottom - mainImageData.y);\n\n            if (mainImageData.mode === 'inside') {\n                w = mainImageData.w;\n                h = mainImageData.h;\n            } else {\n                w = mainImageData.largeWrapperW;\n                h = mainImageData.largeWrapperH;\n            }\n\n            mainImageData.largeImgInMagnifyLensWidth = Math.round(mainImageData.zoom * w);\n            mainImageData.largeImgInMagnifyLensHeight = Math.round(mainImageData.zoom * h);\n\n            mainImageData.lensW = Math.round(mainImageData.w / mainImageData.zoom);\n            mainImageData.lensH = Math.round(mainImageData.h / mainImageData.zoom);\n        }\n\n        function _init($box, options) {\n            var opts = {};\n\n            if (options.thumb === undefined) {\n                return false;\n            }\n\n            $thumb = $box.find(options.thumb);\n\n            if ($thumb.length) {\n                for (var key in options) {\n                    opts[key] = options[key];\n                }\n\n                opts.thumb = $thumb;\n                enabled = opts.enabled;\n\n                if (_toBoolean(enabled)) {\n\n                    $magnifierPreview.show().css('display', '');\n                    $magnifierPreview.addClass(MagnifyCls.magnifyHidden);\n                    set(opts);\n                } else {\n                    $magnifierPreview.empty().hide();\n                }\n            }\n\n            return that;\n        }\n\n        function hoverEvents(thumb) {\n            $(thumb).on('mouseover', function (e) {\n\n                if (showWrapper) {\n\n                    if (magnifierOptions.status !== 0) {\n                        onThumbLeave();\n                    }\n                    handleEvents(e);\n                    isOverThumb = inBounds;\n                }\n            }).trigger('mouseover');\n        }\n\n        function clickEvents(thumb) {\n            $(thumb).on('click', function (e) {\n\n                if (showWrapper) {\n                    if (!isOverThumb) {\n                        if (magnifierOptions.status !== 0) {\n                            onThumbLeave();\n                        }\n                        handleEvents(e);\n                        isOverThumb = true;\n                    }\n                }\n            });\n        }\n\n        function bindEvents(eType, thumb) {\n            var eventFlag = 'hasBoundEvent_' + eType;\n            if (thumb[eventFlag]) {\n                // Events are already bound, no need to bind in duplicate\n                return;\n            }\n            thumb[eventFlag] = true;\n\n            switch (eType) {\n                case 'hover':\n                    hoverEvents(thumb);\n                    break;\n\n                case 'click':\n                    clickEvents(thumb);\n                    break;\n            }\n        }\n\n        function handleEvents(e) {\n            var src = e.target;\n\n            curIdx = src.id;\n            curThumb = src;\n\n            onThumbEnter(src);\n\n            setThumbData(curThumb, magnifierOptions);\n\n            pos.x = e.clientX;\n            pos.y = e.clientY;\n\n            getMousePos();\n            move();\n\n            var handler = magnifierOptions.onthumbenter;\n\n            if (handler !== null) {\n                handler({\n                    thumb: curThumb,\n                    lens: curLens,\n                    large: curLarge,\n                    x: pos.x,\n                    y: pos.y\n                });\n            }\n        }\n\n        function set(options) {\n            if (data[options.thumb.id] !== undefined) {\n                curThumb = options.thumb;\n\n                return false;\n            }\n\n            var thumbObj = new Image(),\n                largeObj = new Image(),\n                $thumb = options.thumb,\n                thumb = $thumb.get(0),\n                idx = thumb.id,\n                largeUrl,\n                largeWrapper = $(options.largeWrapper),\n                zoom = options.zoom || thumb.getAttribute('data-zoom') || gZoom,\n                zoomMin = options.zoomMin || gZoomMin,\n                zoomMax = options.zoomMax || gZoomMax,\n                mode = options.mode || thumb.getAttribute('data-mode') || gMode,\n                eventType = options.eventType || thumb.getAttribute('data-eventType') || gEventType,\n                onthumbenter = options.onthumbenter !== undefined ?\n                    options.onthumbenter\n                    : magnifierOptions.onthumbenter,\n                onthumbleave = options.onthumbleave !== undefined ?\n                    options.onthumbleave\n                    : magnifierOptions.onthumbleave,\n                onthumbmove = options.onthumbmove !== undefined ?\n                    options.onthumbmove\n                    : magnifierOptions.onthumbmove;\n\n            largeUrl = $thumb.data('original') || customUserOptions.full || $thumb.attr('src');\n\n            if (thumb.id === '') {\n                idx = thumb.id = 'magnifier-item-' + gId;\n                gId += 1;\n            }\n\n            createLens(thumb, idx);\n\n            if (options.width) {\n                largeWrapper.width(options.width);\n            }\n\n            if (options.height) {\n                largeWrapper.height(options.height);\n            }\n\n            if (options.top) {\n                if (typeof options.top == 'function') {\n                    var top = options.top() + 'px';\n                } else {\n                    var top = options.top + 'px';\n                }\n\n                if (largeWrapper.length) {\n                    largeWrapper[0].style.top = top.replace('%px', '%');\n                }\n            }\n\n            if (options.left) {\n                if (typeof options.left == 'function') {\n                    var left = options.left() + 'px';\n                } else {\n                    var left = options.left + 'px';\n                }\n\n                if (largeWrapper.length) {\n                    largeWrapper[0].style.left = left.replace('%px', '%');\n                }\n            }\n\n            data[idx] = {\n                zoom: zoom,\n                zoomMin: zoomMin,\n                zoomMax: zoomMax,\n                mode: mode,\n                eventType: eventType,\n                thumbCssClass: thumb.className,\n                zoomAttached: false,\n                status: 0,\n                largeUrl: largeUrl,\n                largeWrapperId: mode === 'outside' ? largeWrapper.attr('id') : null,\n                largeWrapperW: mode === 'outside' ? largeWrapper.width() : null,\n                largeWrapperH: mode === 'outside' ? largeWrapper.height() : null,\n                onthumbenter: onthumbenter,\n                onthumbleave: onthumbleave,\n                onthumbmove: onthumbmove\n            };\n\n            paddingX = ($thumb.parent().width() - $thumb.width()) / 2;\n            paddingY = ($thumb.parent().height() - $thumb.height()) / 2;\n\n            showWrapper = false;\n            $(thumbObj).on('load', function () {\n                if (data.hasOwnProperty(idx)) {\n                    data[idx].status = 1;\n                    $(largeObj).on('load', function () {\n                        if (largeObj.width > largeWrapper.width() || largeObj.height > largeWrapper.height()) {\n                            showWrapper = true;\n                            bindEvents(eventType, thumb);\n                            data[idx].status = 2;\n                            if (largeObj.width > largeObj.height) {\n                                data[idx].zoom = largeObj.width / largeWrapper.width();\n                            } else {\n                                data[idx].zoom = largeObj.height / largeWrapper.height();\n                            }\n                            setThumbData(thumb, data[idx]);\n                            updateLensOnLoad(idx, thumb, largeObj, largeWrapper);\n                        }\n                    });\n                    largeObj.src = data[idx].largeUrl;\n                }\n            });\n\n            thumbObj.src = thumb.src;\n        }\n\n        /**\n         * Hide magnifier when mouse exceeds image bounds.\n         */\n        function onMouseLeave() {\n            onThumbLeave();\n            isOverThumb = false;\n            $magnifierPreview.addClass(MagnifyCls.magnifyHidden);\n        }\n\n        function onMousemove(e) {\n            pos.x = e.clientX;\n            pos.y = e.clientY;\n\n            getMousePos();\n\n            if (gEventType === 'hover') {\n                isOverThumb = inBounds;\n            }\n\n            if (inBounds && isOverThumb) {\n                if (gMode === 'outside') {\n                    $magnifierPreview.removeClass(MagnifyCls.magnifyHidden);\n                }\n                move();\n            }\n        }\n\n        function onScroll() {\n            if (curThumb !== null) {\n                setThumbData(curThumb, magnifierOptions);\n            }\n        }\n\n        $(window).on('scroll', onScroll);\n        $(window).on('resize', function () {\n            _init($box, customUserOptions);\n        });\n\n        $box.on('mousemove', onMousemove);\n        $box.on('mouseleave', onMouseLeave);\n\n        _init($box, customUserOptions);\n    }\n}(jQuery));\n","magnifier/magnify.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'underscore',\n    'magnifier/magnifier'\n], function ($, _) {\n    'use strict';\n\n    return function (config, element) {\n\n        var isTouchEnabled = 'ontouchstart' in document.documentElement,\n            gallerySelector = '[data-gallery-role=\"gallery\"]',\n            magnifierSelector = '[data-gallery-role=\"magnifier\"]',\n            magnifierZoomSelector = '[data-gallery-role=\"magnifier-zoom\"]',\n            zoomInButtonSelector = '[data-gallery-role=\"fotorama__zoom-in\"]',\n            zoomOutButtonSelector = '[data-gallery-role=\"fotorama__zoom-out\"]',\n            fullscreenImageSelector = '[data-gallery-role=\"stage-shaft\"] [data-active=\"true\"] .fotorama__img--full',\n            imageDraggableClass = 'fotorama__img--draggable',\n            imageZoommable = 'fotorama__img--zoommable',\n            zoomInLoaded = 'zoom-in-loaded',\n            zoomOutLoaded = 'zoom-out-loaded',\n            zoomInDisabled = 'fotorama__zoom-in--disabled',\n            zoomOutDisabled = 'fotorama__zoom-out--disabled',\n            keyboardNavigation,\n            videoContainerClass = 'fotorama-video-container',\n            hideMagnifier,\n            dragFlag,\n            endX,\n            transitionEnabled,\n            transitionActive = false,\n            tapFlag = 0,\n            allowZoomOut = false,\n            allowZoomIn = true;\n\n        transitionEnabled = document.documentElement.style.transition !== undefined ||\n            document.documentElement.style.WebkitTransition !== undefined ||\n            document.documentElement.style.MozTransition !== undefined ||\n            document.documentElement.style.MsTransition !== undefined ||\n            document.documentElement.style.OTransition !== undefined;\n\n        /**\n         * Return width and height of original image\n         * @param img original image node\n         * @returns {{rw: number, rh: number}}\n         */\n        function getImageSize(img) {\n            return {\n                rw: img.naturalWidth,\n                rh: img.naturalHeight\n            };\n        }\n\n        /**\n         * Sets min-height and min-width for image to avoid transition bug\n         * @param $image - fullscreen image\n         */\n        function calculateMinSize($image) {\n\n            var minHeight,\n                minWidth,\n                height = $image.height(),\n                width = $image.width(),\n                parentHeight = $image.parent().height(),\n                parentWidth = $image.parent().width();\n\n            if (width > parentWidth || height > parentHeight) {\n\n                if (width / height < parentWidth / parentHeight) {\n                    minHeight = parentHeight;\n                    minWidth = width * (parentHeight / height);\n                } else {\n                    minWidth = parentWidth;\n                    minHeight = height * parentWidth / width;\n                }\n                $image.css({\n                    'min-width': minWidth,\n                    'min-height': minHeight\n                });\n            }\n        }\n\n        function toggleZoomable($image, flag) {\n            if (flag) {\n                $image.css({\n                    'min-width': $image.width(),\n                    'min-height': $image.height(),\n                    'width': $image.width(),\n                    'height': $image.height()\n                }).addClass(imageZoommable);\n            } else {\n                $image.css({\n                    width: '',\n                    height: '',\n                    top: '',\n                    left: '',\n                    right: '',\n                    bottom: ''\n                }).removeClass(imageZoommable);\n                calculateMinSize($image);\n            }\n        }\n\n        function resetVars($image) {\n            allowZoomIn = true;\n            allowZoomOut = dragFlag = transitionActive = false;\n            $image.hasClass(imageDraggableClass) && $image.removeClass(imageDraggableClass);\n            toggleZoomable($image, false);\n        }\n\n        /**\n         * Set state for zoom controls.\n         * If state is true, zoom controls will be visible.\n         * IF state is false, zoom controls will be hidden.\n         * @param isHide\n         */\n        function hideZoomControls(isHide) {\n            if (isHide) {\n                $(zoomInButtonSelector).addClass(zoomInDisabled);\n                $(zoomOutButtonSelector).addClass(zoomOutDisabled);\n            } else {\n                $(zoomInButtonSelector).removeClass(zoomInDisabled);\n                $(zoomOutButtonSelector).removeClass(zoomOutDisabled);\n            }\n        }\n\n        /**\n         * Asynchronus control visibility of zoom buttons.\n         * If image bigger than her wrapper. Zoom controls must visible.\n         * @param path - image source path\n         * @param $image\n         */\n        function asyncToggleZoomButtons(path, $image) {\n            var img = new Image();\n\n            img.onload = function () {\n                this.height > $image.parent().height() || this.width > $image.parent().width() ?\n                    hideZoomControls(false) : hideZoomControls(true);\n            };\n            img.src = path;\n        }\n\n        /**\n         * Control visibility of zoom buttons.\n         * Zoom controls must be invisible for video content and touch devices.\n         * On touch devices active pinchIn/pinchOut.\n         * @param $image\n         * @param isTouchScreen - true for touch devices\n         * @param isVideoActiveFrame - true for active video frame\n         */\n        function toggleZoomButtons($image, isTouchScreen, isVideoActiveFrame) {\n            var path = $image.attr('src');\n\n            if (path && !isTouchScreen && !isVideoActiveFrame) {\n                asyncToggleZoomButtons(path, $image);\n            } else {\n                hideZoomControls(true);\n            }\n        }\n\n        /**\n         * Handle resize event in fullscreen.\n         * @param $image - Fullscreen image.\n         * @param e - Event.\n         */\n        function resizeHandler(e, $image) {\n            var imageSize,\n                parentWidth,\n                parentHeight,\n                isImageSmall,\n                isImageFit;\n\n            if (!e.data.$image || !e.data.$image.length)\n                return;\n\n            imageSize = getImageSize($(fullscreenImageSelector)[0]);\n            parentWidth = e.data.$image.parent().width();\n            parentHeight = e.data.$image.parent().height();\n            isImageSmall = parentWidth >= imageSize.rw && parentHeight >= imageSize.rh;\n            isImageFit = parentWidth > e.data.$image.width() && parentHeight > e.data.$image.height();\n\n            toggleZoomButtons(e.data.$image, isTouchEnabled, checkForVideo(e.data.fotorama.activeFrame.$stageFrame));\n            calculateMinSize(e.data.$image);\n\n            if (e.data.$image.hasClass(imageZoommable) && !allowZoomOut || isImageSmall || isImageFit) {\n                resetVars(e.data.$image);\n            }\n\n            if (!isImageSmall) {\n                toggleStandartNavigation();\n            }\n        }\n\n        function getTopValue($image, topProp, step, height, containerHeight) {\n            var top;\n\n            if (parseInt($image.css('marginTop')) || parseInt($image.css('marginLeft'))) {\n                top = dragFlag ? topProp - step / 4 : 0;\n                top = top < containerHeight - height ? containerHeight - height : top;\n                top = top > height - containerHeight ? height - containerHeight : top;\n            } else {\n                top = topProp + step / 2;\n                top = top < containerHeight - height ? containerHeight - height : top;\n                top = top > 0 ? 0 : top;\n\n                if (!dragFlag && step < 0) {\n                    top = top < (containerHeight - height) / 2 ? (containerHeight - height) / 2 : top;\n                }\n            }\n\n            return top;\n        }\n\n        function getLeftValue(leftProp, step, width, containerWidth) {\n            var left;\n\n            left = leftProp + step / 2;\n            left = left < containerWidth - width ? containerWidth - width : left;\n            left = left > 0 ? 0 : left;\n\n            if (!dragFlag && step < 0) {\n                left = left < (containerWidth - width) / 2 ? (containerWidth - width) / 2 : left;\n            }\n\n            return left;\n        }\n\n        function checkFullscreenImagePosition($image, dimentions, widthStep, heightStep) {\n            var $imageContainer,\n                containerWidth,\n                containerHeight,\n                settings,\n                top,\n                left,\n                right,\n                bottom,\n                ratio;\n\n            if ($(gallerySelector).data('fotorama').fullScreen) {\n                transitionActive = true;\n                $imageContainer = $image.parent();\n                containerWidth = $imageContainer.width();\n                containerHeight = $imageContainer.height();\n                top = $image.position().top;\n                left = $image.position().left;\n                ratio = $image.width() / $image.height();\n                dimentions.height = isNaN(dimentions.height) ? dimentions.width / ratio : dimentions.height;\n                dimentions.width = isNaN(dimentions.width) ? dimentions.height * ratio : dimentions.width;\n\n                top = dimentions.height >= containerHeight ?\n                    getTopValue($image, top, heightStep, dimentions.height, containerHeight) : 0;\n\n                left = dimentions.width >= containerWidth ?\n                    getLeftValue(left, widthStep, dimentions.width, containerWidth) : 0;\n\n                right = dragFlag && left < (containerWidth - dimentions.width) / 2 ? 0 : left;\n                bottom = dragFlag ? 0 : top;\n\n                settings = $.extend(dimentions, {\n                    top: top,\n                    left: left,\n                    right: right\n                });\n\n                $image.css(settings);\n            }\n        }\n\n        /**\n         * Toggles fotorama's keyboard and mouse/touch navigation.\n         */\n        function toggleStandartNavigation() {\n            var $selectable =\n                    $('a[href], area[href], input, select, textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]')\n                    .not('[tabindex=-1], [disabled], :hidden'),\n                fotorama = $(gallerySelector).data('fotorama'),\n                $focus = $(':focus'),\n                index;\n\n            if (fotorama.fullScreen) {\n\n                $selectable.each(function (number) {\n\n                    if ($(this).is($focus)) {\n                        index = number;\n                    }\n                });\n\n                fotorama.setOptions({\n                    swipe: !allowZoomOut,\n                    keyboard: !allowZoomOut\n                });\n\n                if (_.isNumber(index)) {\n                    $selectable.eq(index).trigger('focus');\n                }\n            }\n        }\n\n        function zoomIn(e, xStep, yStep) {\n            var $image,\n                imgOriginalSize,\n                imageWidth,\n                imageHeight,\n                zoomWidthStep,\n                zoomHeightStep,\n                widthResult,\n                heightResult,\n                ratio,\n                dimentions = {};\n\n            if (allowZoomIn && (!transitionEnabled || !transitionActive) && (isTouchEnabled ||\n                !$(zoomInButtonSelector).hasClass(zoomInDisabled))) {\n                $image = $(fullscreenImageSelector);\n                imgOriginalSize = getImageSize($image[0]);\n                imageWidth = $image.width();\n                imageHeight = $image.height();\n                ratio = imageWidth / imageHeight;\n                allowZoomOut = true;\n                toggleStandartNavigation();\n\n                if (!$image.hasClass(imageZoommable)) {\n                    toggleZoomable($image, true);\n                }\n\n                e.preventDefault();\n\n                if (imageWidth >= imageHeight) {\n                    zoomWidthStep = xStep || Math.ceil(imageWidth * parseFloat(config.magnifierOpts.fullscreenzoom) / 100);\n                    widthResult = imageWidth + zoomWidthStep;\n\n                    if (widthResult >= imgOriginalSize.rw) {\n                        widthResult = imgOriginalSize.rw;\n                        zoomWidthStep = xStep || widthResult - imageWidth;\n                        allowZoomIn = false;\n                    }\n                    heightResult = widthResult / ratio;\n                    zoomHeightStep = yStep || heightResult - imageHeight;\n                } else {\n                    zoomHeightStep = yStep || Math.ceil(imageHeight * parseFloat(config.magnifierOpts.fullscreenzoom) / 100);\n                    heightResult = imageHeight + zoomHeightStep;\n\n                    if (heightResult >= imgOriginalSize.rh) {\n                        heightResult = imgOriginalSize.rh;\n                        zoomHeightStep = yStep || heightResult - imageHeight;\n                        allowZoomIn = false;\n                    }\n                    widthResult = heightResult * ratio;\n                    zoomWidthStep = xStep || widthResult - imageWidth;\n                }\n\n                if (imageWidth >= imageHeight && imageWidth !== imgOriginalSize.rw) {\n                    dimentions = $.extend(dimentions, {\n                        width: widthResult,\n                        height: 'auto'\n                    });\n                    checkFullscreenImagePosition($image, dimentions, -zoomWidthStep, -zoomHeightStep);\n\n                } else if (imageWidth < imageHeight && imageHeight !== imgOriginalSize.rh) {\n                    dimentions = $.extend(dimentions, {\n                        width: 'auto',\n                        height: heightResult\n                    });\n                    checkFullscreenImagePosition($image, dimentions, -zoomWidthStep, -zoomHeightStep);\n                }\n            }\n\n            return false;\n        }\n\n        function zoomOut(e, xStep, yStep) {\n            var $image,\n                widthResult,\n                heightResult,\n                dimentions,\n                parentWidth,\n                parentHeight,\n                imageWidth,\n                imageHeight,\n                zoomWidthStep,\n                zoomHeightStep,\n                ratio,\n                fitIntoParent;\n\n            if (allowZoomOut && (!transitionEnabled || !transitionActive) && (isTouchEnabled ||\n                !$(zoomOutButtonSelector).hasClass(zoomOutDisabled))) {\n                allowZoomIn = true;\n                $image = $(fullscreenImageSelector);\n                parentWidth = $image.parent().width();\n                parentHeight = $image.parent().height();\n                imageWidth = $image.width();\n                imageHeight = $image.height();\n                ratio = imageWidth / imageHeight;\n\n                e.preventDefault();\n\n                if (imageWidth >= imageHeight) {\n                    zoomWidthStep = xStep || Math.ceil(imageWidth * parseFloat(config.magnifierOpts.fullscreenzoom) / 100);\n                    widthResult = imageWidth - zoomWidthStep;\n                    heightResult = widthResult / ratio;\n                    zoomHeightStep = yStep || imageHeight - heightResult;\n                } else {\n                    zoomHeightStep = yStep || Math.ceil(imageHeight * parseFloat(config.magnifierOpts.fullscreenzoom) / 100);\n                    heightResult = imageHeight - zoomHeightStep;\n                    widthResult = heightResult * ratio;\n                    zoomWidthStep = xStep || imageWidth - widthResult;\n                }\n\n                fitIntoParent = function () {\n                    if (ratio > parentWidth / parentHeight) {\n                        widthResult = parentWidth;\n                        zoomWidthStep = imageWidth - widthResult;\n                        heightResult = widthResult / ratio;\n                        zoomHeightStep = imageHeight - heightResult;\n                        dimentions = {\n                            width: widthResult,\n                            height: 'auto'\n                        };\n                    } else {\n                        heightResult = parentHeight;\n                        zoomHeightStep = imageHeight - heightResult;\n                        widthResult = heightResult * ratio;\n                        zoomWidthStep = imageWidth - widthResult;\n                        dimentions = {\n                            width: 'auto',\n                            height: heightResult\n                        };\n                    }\n                    checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);\n                };\n\n                if (imageWidth >= imageHeight) {\n                    if (widthResult > parentWidth) {\n                        dimentions = {\n                            width: widthResult,\n                            height: 'auto'\n                        };\n                        checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);\n                    } else if (heightResult > parentHeight) {\n                        dimentions = {\n                            width: widthResult,\n                            height: 'auto'\n                        };\n                        checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);\n                    } else {\n                        allowZoomOut = dragFlag = false;\n                        toggleStandartNavigation();\n                        fitIntoParent();\n                    }\n                } else if (heightResult > parentHeight) {\n                    dimentions = {\n                        width: 'auto',\n                        height: heightResult\n                    };\n                    checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);\n                } else if (widthResult > parentWidth) {\n                    dimentions = {\n                        width: 'auto',\n                        height: heightResult\n                    };\n                    checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);\n                } else {\n                    allowZoomOut = dragFlag = false;\n                    toggleStandartNavigation();\n                    fitIntoParent();\n                }\n            }\n\n            return false;\n        }\n\n        /**\n         * Bind event on scroll on active item in fotorama\n         * @param e\n         * @param fotorama - object of fotorama\n         */\n        function mousewheel(e, fotorama, element) {\n            var $fotoramaStage = fotorama.activeFrame.$stageFrame,\n                fotoramaStage = $fotoramaStage.get(0);\n\n            function onWheel(e) {\n                var delta = e.deltaY || e.wheelDelta,\n                    ev = e || window.event;\n\n                if ($(gallerySelector).data('fotorama').fullScreen) {\n\n                    if (e.deltaY) {\n                        if (delta > 0) {\n                            zoomOut(ev);\n                        } else {\n                            zoomIn(ev);\n                        }\n                    } else if (delta > 0) {\n                        zoomIn(ev);\n                    } else {\n                        zoomOut(ev);\n                    }\n\n                    e.preventDefault ? e.preventDefault() : e.returnValue = false;\n                }\n            }\n\n            if (!$fotoramaStage.hasClass('magnify-wheel-loaded')) {\n                if (fotoramaStage && fotoramaStage.addEventListener) {\n                    if ('onwheel' in document) {\n                        fotoramaStage.addEventListener('wheel', onWheel, { passive: false });\n                    } else if ('onmousewheel' in document) {\n                        fotoramaStage.addEventListener('mousewheel', onWheel);\n                    } else {\n                        fotoramaStage.addEventListener('MozMousePixelScroll', onWheel);\n                    }\n                    $fotoramaStage.addClass('magnify-wheel-loaded');\n                }\n            }\n        }\n\n        /**\n         * Method which makes draggable picture. Also work on touch devices.\n         */\n        function magnifierFullscreen(fotorama) {\n            var isDragActive = false,\n                startX,\n                startY,\n                imagePosX,\n                imagePosY,\n                touch,\n                swipeSlide,\n                $gallery = $(gallerySelector),\n                $image = $(fullscreenImageSelector, $gallery),\n                $imageContainer = $('[data-gallery-role=\"stage-shaft\"] [data-active=\"true\"]'),\n                gallery = $gallery.data('fotorama'),\n                pinchDimention;\n\n            swipeSlide = _.throttle(function (direction) {\n                $(gallerySelector).data('fotorama').show(direction);\n            }, 500, {\n                trailing: false\n            });\n\n            /**\n             * Returns top position value for passed jQuery object.\n             *\n             * @param $el\n             * @return {number}\n             */\n            function getTop($el) {\n                return parseInt($el.get(0).style.top);\n            }\n\n            function shiftImage(dx, dy, e) {\n                var top = +imagePosY + dy,\n                    left = +imagePosX + dx,\n                    swipeCondition = $image.width() / 10 + 20;\n\n                dragFlag = true;\n\n                if ($image.offset().left === $imageContainer.offset().left + $imageContainer.width() - $image.width() && e.keyCode === 39 ||\n                    endX - 1 < $imageContainer.offset().left + $imageContainer.width() - $image.width() && dx < 0 &&\n                    _.isNumber(endX) &&\n                    (e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'pointermove' || e.type === 'MSPointerMove')) {\n                    endX = null;\n                    swipeSlide('>');\n\n                    return;\n                }\n\n                if ($image.offset().left === $imageContainer.offset().left && dx !== 0 && e.keyCode === 37 ||\n                    endX === $imageContainer.offset().left && dx > 0 &&\n                    (e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'pointermove' || e.type === 'MSPointerMove')) {\n                    endX = null;\n                    swipeSlide('<');\n\n                    return;\n                }\n\n                if ($image.height() > $imageContainer.height()) {\n                    if ($imageContainer.height() > $image.height() + top) {\n                        $image.css('top', $imageContainer.height() - $image.height());\n                    } else {\n                        top = $image.height() - getTop($image) - $imageContainer.height();\n                        dy = dy < top ? dy : top;\n                        $image.css('top', getTop($image) + dy);\n                    }\n                }\n\n                if ($image.width() > $imageContainer.width()) {\n\n                    if ($imageContainer.offset().left + $imageContainer.width() > left + $image.width()) {\n                        left = $imageContainer.offset().left + $imageContainer.width() - $image.width();\n                    } else {\n                        left = $imageContainer.offset().left < left ? $imageContainer.offset().left : left;\n                    }\n                    $image.offset({\n                        'left': left\n                    });\n                    $image.css('right', '');\n                } else if (Math.abs(dy) < 1 && allowZoomOut &&\n                    !(e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'pointermove' || e.type === 'MSPointerMove')) {\n                    dx < 0 ? $(gallerySelector).data('fotorama').show('>') : $(gallerySelector).data('fotorama').show('<');\n                }\n\n                if ($image.width() <= $imageContainer.width() && allowZoomOut &&\n                    (e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'pointermove' || e.type === 'MSPointerMove') &&\n                    Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > swipeCondition) {\n                    dx < 0 ? swipeSlide('>') : swipeSlide('<');\n                }\n            }\n\n            /**\n             * Sets image size to original or fit in parent block\n             * @param e - event object\n             */\n            function dblClickHandler(e) {\n                var imgOriginalSize = getImageSize($image[0]),\n                    proportions;\n\n                if (imgOriginalSize.rh < $image.parent().height() && imgOriginalSize.rw < $image.parent().width()) {\n                    return;\n                }\n\n                proportions = imgOriginalSize.rw / imgOriginalSize.rh;\n\n                if (allowZoomIn) {\n                    zoomIn(e, imgOriginalSize.rw - $image.width(), imgOriginalSize.rh - $image.height());\n                } else if (proportions > $imageContainer.width() / $imageContainer.height()) {\n                    zoomOut(e, imgOriginalSize.rw - $imageContainer.width(), imgOriginalSize.rw / proportions);\n                } else {\n                    zoomOut(e, imgOriginalSize.rw * proportions, imgOriginalSize.rh - $imageContainer.height());\n                }\n            }\n\n            function detectDoubleTap(e) {\n                var now = new Date().getTime(),\n                    timesince = now - tapFlag;\n\n                if (timesince < 400 && timesince > 0) {\n                    transitionActive = false;\n                    tapFlag = 0;\n                    dblClickHandler(e);\n                } else {\n                    tapFlag = new Date().getTime();\n                }\n            }\n\n            if (isTouchEnabled) {\n                $image.off('tap');\n                $image.on('tap', function (e) {\n                    if (e.originalEvent.originalEvent.touches.length === 0) {\n                        detectDoubleTap(e);\n                    }\n                });\n            } else {\n                $image.off('dblclick');\n                $image.on('dblclick', dblClickHandler);\n            }\n\n            if (gallery.fullScreen) {\n                toggleZoomButtons($image, isTouchEnabled, checkForVideo(fotorama.activeFrame.$stageFrame));\n            }\n\n            function getDimention(event) {\n                return Math.sqrt(\n                    (event.touches[0].clientX - event.touches[1].clientX) * (event.touches[0].clientX - event.touches[1].clientX) +\n                    (event.touches[0].clientY - event.touches[1].clientY) * (event.touches[0].clientY - event.touches[1].clientY));\n            }\n\n            $image.off(isTouchEnabled ? 'touchstart' : 'pointerdown mousedown MSPointerDown');\n            $image.on(isTouchEnabled ? 'touchstart' : 'pointerdown mousedown MSPointerDown', function (e) {\n                if (e && e.originalEvent.touches && e.originalEvent.touches.length >= 2) {\n                    e.preventDefault();\n                    pinchDimention = getDimention(e.originalEvent);\n                    isDragActive = false;\n\n                    if ($image.hasClass(imageDraggableClass)) {\n                        $image.removeClass(imageDraggableClass);\n                    }\n                } else if (gallery.fullScreen && (!transitionEnabled || !transitionActive)) {\n                    imagePosY = getTop($image);\n                    imagePosX = $image.offset().left;\n\n                    if (isTouchEnabled) {\n                        touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];\n                        e.clientX = touch.pageX;\n                        e.clientY = touch.pageY;\n                    }\n                    startX = e.clientX || e.originalEvent.clientX;\n                    startY = e.clientY || e.originalEvent.clientY;\n                    isDragActive = true;\n                }\n\n                if ($image.offset() && $image.width() > $imageContainer.width()) {\n                    endX = $image.offset().left;\n                }\n            });\n\n            $image.off(isTouchEnabled ? 'touchmove' : 'mousemove pointermove MSPointerMove');\n            $image.on(isTouchEnabled ? 'touchmove' : 'mousemove pointermove MSPointerMove', function (e) {\n                if (e && e.originalEvent.touches && e.originalEvent.touches.length >= 2) {\n                    e.preventDefault();\n                    var currentDimention = getDimention(e.originalEvent);\n\n                    if ($image.hasClass(imageDraggableClass)) {\n                        $image.removeClass(imageDraggableClass);\n                    }\n\n                    if (currentDimention < pinchDimention) {\n                        zoomOut(e);\n                        pinchDimention = currentDimention;\n                    } else if (currentDimention > pinchDimention) {\n                        zoomIn(e);\n                        pinchDimention = currentDimention;\n                    }\n                } else {\n                    var clientX,\n                        clientY;\n\n                    if (gallery.fullScreen && isDragActive && (!transitionEnabled || !transitionActive)) {\n\n                        if (allowZoomOut && !$image.hasClass(imageDraggableClass)) {\n                            $image.addClass(imageDraggableClass);\n                        }\n                        clientX = e.clientX || e.originalEvent.clientX;\n                        clientY = e.clientY || e.originalEvent.clientY;\n\n                        e.preventDefault();\n\n                        if (isTouchEnabled) {\n                            touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];\n                            clientX = touch.pageX;\n                            clientY = touch.pageY;\n                        }\n\n                        if (allowZoomOut) {\n                            imagePosY = getTop($(fullscreenImageSelector, $gallery));\n                            shiftImage(clientX - startX, clientY - startY, e);\n                        }\n                    }\n                }\n            });\n\n            $image.off('transitionend webkitTransitionEnd mozTransitionEnd msTransitionEnd ');\n            $image.on('transitionend webkitTransitionEnd mozTransitionEnd msTransitionEnd', function () {\n                transitionActive = false;\n            });\n\n            if (keyboardNavigation) {\n                $(document).off('keydown', keyboardNavigation);\n            }\n\n            /**\n             * Replaces original navigations with better one\n             * @param e - event object\n             */\n            keyboardNavigation = function (e) {\n                var step = 40,\n                    $focus = $(':focus'),\n                    isFullScreen = $(gallerySelector).data('fotorama').fullScreen,\n                    initVars = function () {\n                        imagePosX = $(fullscreenImageSelector, $gallery).offset().left;\n                        imagePosY = getTop($(fullscreenImageSelector, $gallery));\n                    };\n\n                if (($focus.attr('data-gallery-role') || !$focus.length) && allowZoomOut) {\n                    if (isFullScreen) {\n                        imagePosX = $(fullscreenImageSelector, $(gallerySelector)).offset().left;\n                        imagePosY = getTop($(fullscreenImageSelector, $(gallerySelector)));\n                    }\n\n                    if (e.keyCode === 39) {\n\n                        if (isFullScreen) {\n                            initVars();\n                            shiftImage(-step, 0, e);\n                        }\n                    }\n\n                    if (e.keyCode === 38) {\n\n                        if (isFullScreen) {\n                            initVars();\n                            shiftImage(0, step, e);\n                        }\n                    }\n\n                    if (e.keyCode === 37) {\n\n                        if (isFullScreen) {\n                            initVars();\n                            shiftImage(step, 0, e);\n                        }\n                    }\n\n                    if (e.keyCode === 40) {\n\n                        if (isFullScreen) {\n                            e.preventDefault();\n                            initVars();\n                            shiftImage(0, -step, e);\n                        }\n                    }\n                }\n\n                if (e.keyCode === 27 && isFullScreen && allowZoomOut) {\n                    $(gallerySelector).data('fotorama').cancelFullScreen();\n                }\n            };\n\n            /**\n             * @todo keyboard navigation through Fotorama Api.\n             */\n            $(document).on('keydown', keyboardNavigation);\n\n            $(document).on(isTouchEnabled ? 'touchend' : 'mouseup pointerup MSPointerUp', function (e) {\n                if (gallery.fullScreen) {\n\n                    if ($image.offset() && $image.width() > $imageContainer.width()) {\n                        endX = $image.offset().left;\n                    }\n\n                    isDragActive = false;\n                    $image.removeClass(imageDraggableClass);\n                }\n            });\n\n            $(window).off('resize', resizeHandler);\n            $(window).on('resize', {\n                $image: $image,\n                fotorama: fotorama\n            }, resizeHandler);\n        }\n\n        /**\n         * Hides magnifier preview and zoom blocks.\n         */\n        hideMagnifier = function () {\n            $(magnifierSelector).empty().hide();\n            $(magnifierZoomSelector).remove();\n        };\n\n        /**\n         * Check is active frame in gallery include video content.\n         * If true activeFrame contain video.\n         * @param $stageFrame - active frame in gallery\n         * @returns {*|Boolean}\n         */\n        function checkForVideo($stageFrame) {\n            return $stageFrame.hasClass(videoContainerClass);\n        }\n\n        /**\n         * Hides magnifier on drag and while arrow click.\n         */\n        function behaveOnDrag(e, initPos) {\n            var pos = [e.pageX, e.pageY],\n                isArrow = $(e.target).data('gallery-role') === 'arrow',\n                isClick = initPos[0] === pos[0] && initPos[1] === pos[1],\n                isImg = $(e.target).parent().data('active');\n\n            if (isArrow || isImg && !isClick) {\n                hideMagnifier();\n            }\n        }\n\n        if (config.magnifierOpts.enabled) {\n            $(element).on('pointerdown mousedown MSPointerDown', function (e) {\n                var pos = [e.pageX, e.pageY];\n\n                $(element).on('mousemove pointermove MSPointerMove', function (ev) {\n                    navigator.msPointerEnabled ? hideMagnifier() : behaveOnDrag(ev, pos);\n                });\n                $(document).on('mouseup pointerup MSPointerUp', function () {\n                    $(element).off('mousemove pointermove MSPointerMove');\n                });\n            });\n        }\n\n        $.extend(config.magnifierOpts, {\n            zoomable: false,\n            thumb: '.fotorama__img',\n            largeWrapper: '[data-gallery-role=\"magnifier\"]',\n            height: config.magnifierOpts.height || function () {\n                return $('[data-active=\"true\"]').height();\n            },\n            width: config.magnifierOpts.width || function () {\n                var productMedia = $(gallerySelector).parent().parent();\n\n                return productMedia.parent().width() - productMedia.width() - 20;\n            },\n            left: config.magnifierOpts.left || function () {\n                return $(gallerySelector).offset().left + $(gallerySelector).width() + 20;\n            },\n            top: config.magnifierOpts.top || function () {\n                return $(gallerySelector).offset().top;\n            }\n        });\n\n        $(element).on('fotorama:load fotorama:showend fotorama:fullscreenexit fotorama:ready', function (e, fotorama) {\n            var $activeStageFrame = $(gallerySelector).data('fotorama').activeFrame.$stageFrame;\n\n            if (!$activeStageFrame.find(magnifierZoomSelector).length) {\n                hideMagnifier();\n\n                if (config.magnifierOpts) {\n                    config.magnifierOpts.large = $(gallerySelector).data('fotorama').activeFrame.img;\n                    config.magnifierOpts.full = fotorama.data[fotorama.activeIndex].original;\n                    !checkForVideo($activeStageFrame) && $($activeStageFrame).magnify(config.magnifierOpts);\n                }\n            }\n        });\n\n        $(element).on('gallery:loaded', function (e) {\n            var $prevImage;\n\n            $(element).find(gallerySelector)\n                .on('fotorama:ready', function (e, fotorama) {\n                    var $zoomIn = $(zoomInButtonSelector),\n                        $zoomOut = $(zoomOutButtonSelector);\n\n                    if (!$zoomIn.hasClass(zoomInLoaded)) {\n                        $zoomIn.on('click touchstart', zoomIn);\n                        $zoomIn.on('mousedown', function (e) {\n                            e.stopPropagation();\n                        });\n\n                        $zoomIn.on('keyup', function (e) {\n\n                            if (e.keyCode === 13) {\n                                zoomIn(e);\n                            }\n                        });\n\n                        $(window).on('keyup', function (e) {\n\n                            if (e.keyCode === 107 || fotorama.fullscreen) {\n                                zoomIn(e);\n                            }\n                        });\n\n                        $zoomIn.addClass(zoomInLoaded);\n                    }\n\n                    if (!$zoomOut.hasClass(zoomOutLoaded)) {\n                        $zoomOut.on('click touchstart', zoomOut);\n                        $zoomOut.on('mousedown', function (e) {\n                            e.stopPropagation();\n                        });\n\n                        $zoomOut.on('keyup', function (e) {\n\n                            if (e.keyCode === 13) {\n                                zoomOut(e);\n                            }\n                        });\n\n                        $(window).on('keyup', function (e) {\n\n                            if (e.keyCode === 109 || fotorama.fullscreen) {\n                                zoomOut(e);\n                            }\n                        });\n\n                        $zoomOut.addClass(zoomOutLoaded);\n                    }\n                })\n                .on('fotorama:fullscreenenter fotorama:showend', function (e, fotorama) {\n                    hideMagnifier();\n\n                    if (!$(fullscreenImageSelector).is($prevImage)) {\n                        resetVars($(fullscreenImageSelector));\n                    }\n                    magnifierFullscreen(fotorama);\n                    mousewheel(e, fotorama, element);\n\n                    if ($prevImage) {\n                        calculateMinSize($prevImage);\n\n                        if (!$(fullscreenImageSelector).is($prevImage)) {\n                            resetVars($prevImage);\n                        }\n                    }\n\n                    toggleStandartNavigation();\n                })\n                .on('fotorama:load', function (e, fotorama) {\n                    if ($(gallerySelector).data('fotorama').fullScreen) {\n                        toggleZoomButtons($(fullscreenImageSelector), isTouchEnabled,\n                            checkForVideo(fotorama.activeFrame.$stageFrame));\n                    }\n                    magnifierFullscreen(fotorama);\n                })\n                .on('fotorama:show', function (e, fotorama) {\n                    $prevImage = _.clone($(fullscreenImageSelector));\n                    hideMagnifier();\n                })\n                .on('fotorama:fullscreenexit', function (e, fotorama) {\n                    resetVars($(fullscreenImageSelector));\n                    hideMagnifier();\n                    hideZoomControls(true);\n                });\n        });\n\n        return config;\n    };\n});\n","Magento_ProductAlert/js/form-submitter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery'\n], function ($) {\n    'use strict';\n\n    return function (data, element) {\n\n        $(element).trigger('submit');\n    };\n});\n","Magento_GiftMessage/js/gift-options.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.giftOptions', {\n        options: {\n            mageError: 'mage-error',\n            noDisplay: 'no-display',\n            requiredEntry: 'required-entry'\n        },\n\n        /**\n         * Initial toggle of the various gift options after widget instantiation.\n         * @private\n         */\n        _init: function () {\n            this._toggleVisibility();\n        },\n\n        /**\n         * Bind a click handler to the widget's context element.\n         * @private\n         */\n        _create: function () {\n            this.element.on('click', $.proxy(this._toggleVisibility, this));\n            $(this.element.data('selector').id).find('.giftmessage-area')\n                .on('change', $.proxy(this._toggleRequired, this));\n        },\n\n        /**\n         * Toggle the visibility of the widget's context element's selector(s).\n         * @private\n         * @param {jQuery.Event} event - Click event. Target is a checkbox.\n         */\n        _toggleVisibility: function (event) {\n            var checkbox = event ? $(event.target) : this.element,\n                container = $(checkbox.data('selector').id),\n                _this;\n\n            if (checkbox.is(':checked')) {\n                container.show()\n                    .find('.giftmessage-area:not(:visible)').each(function (x, element) {\n                        if ($(element).val().length > 0) {\n                            $(element).trigger('change');\n                            container.find('a').trigger('click');\n                        }\n                    });\n            } else {\n                _this = this;\n                container.hide()\n                    .find('.input-text:not(.giftmessage-area)').each(function (x, element) {\n                        $(element).val(element.defaultValue).removeClass(_this.options.mageError)\n                            .next('div.' + _this.options.mageError).remove();\n                    }).end()\n                    .find('.giftmessage-area').val('').change().end()\n                    .find('.select').val('').change().end()\n                    .find('.checkbox:checked').prop('checked', false).trigger('click').prop('checked', false).end()\n                    .find('.price-box').addClass(this.options.noDisplay).end();\n            }\n        },\n\n        /**\n         * Make the From and To input fields required if a gift message has been written.\n         * @private\n         * @param {jQuery.Event} event - Change event. Target is a textarea.\n         */\n        _toggleRequired: function (event) {\n            var textArea = $(event.target),\n                length = textArea.val().length;\n\n            textArea.closest('li').prev('.fields')\n                .find('.input-text').toggleClass(this.options.requiredEntry, length > 0);\n        }\n    });\n\n    return $.mage.giftOptions;\n});\n","Magento_GiftMessage/js/action/gift-options.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'Magento_GiftMessage/js/model/url-builder',\n    'mage/storage',\n    'Magento_Ui/js/model/messageList',\n    'Magento_Checkout/js/model/error-processor',\n    'mage/url',\n    'Magento_Checkout/js/model/quote',\n    'underscore'\n], function (urlBuilder, storage, messageList, errorProcessor, url, quote, _) {\n    'use strict';\n\n    return function (giftMessage, remove) {\n        var serviceUrl;\n\n        url.setBaseUrl(giftMessage.getConfigValue('baseUrl'));\n\n        if (giftMessage.getConfigValue('isCustomerLoggedIn')) {\n            serviceUrl = urlBuilder.createUrl('/carts/mine/gift-message', {});\n\n            if (giftMessage.itemId != 'orderLevel') { //eslint-disable-line eqeqeq\n                serviceUrl = urlBuilder.createUrl('/carts/mine/gift-message/:itemId', {\n                    itemId: giftMessage.itemId\n                });\n            }\n        } else {\n            serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/gift-message', {\n                cartId: quote.getQuoteId()\n            });\n\n            if (giftMessage.itemId != 'orderLevel') { //eslint-disable-line eqeqeq\n                serviceUrl = urlBuilder.createUrl(\n                    '/guest-carts/:cartId/gift-message/:itemId',\n                    {\n                        cartId: quote.getQuoteId(), itemId: giftMessage.itemId\n                    }\n                );\n            }\n        }\n        messageList.clear();\n\n        storage.post(\n            serviceUrl,\n            JSON.stringify({\n                'gift_message': giftMessage.getSubmitParams(remove)\n            })\n        ).done(function () {\n            giftMessage.reset();\n            _.each(giftMessage.getAfterSubmitCallbacks(), function (callback) {\n                if (_.isFunction(callback)) {\n                    callback();\n                }\n            });\n        }).fail(function (response) {\n            errorProcessor.process(response);\n        });\n    };\n});\n","Magento_GiftMessage/js/view/gift-message.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_GiftMessage/js/model/gift-message',\n    'Magento_GiftMessage/js/model/gift-options',\n    'Magento_GiftMessage/js/action/gift-options'\n], function (Component, GiftMessage, giftOptions, giftOptionsService) {\n    'use strict';\n\n    return Component.extend({\n        formBlockVisibility: null,\n        resultBlockVisibility: null,\n        model: {},\n\n        /**\n         * Component init\n         */\n        initialize: function () {\n            var self = this,\n                model;\n\n            this._super()\n                .observe('formBlockVisibility')\n                .observe({\n                    'resultBlockVisibility': false\n                });\n\n            this.itemId = this.itemId || 'orderLevel';\n            model = new GiftMessage(this.itemId);\n            this.model = model;\n            this.isResultBlockVisible();\n            giftOptions.addOption(model);\n\n            this.model.getObservable('isClear').subscribe(function (value) {\n                if (value == true) { //eslint-disable-line eqeqeq\n                    self.formBlockVisibility(false);\n                    self.model.getObservable('alreadyAdded')(true);\n                }\n            });\n        },\n\n        /**\n         * Is reslt block visible\n         */\n        isResultBlockVisible: function () {\n            var self = this;\n\n            if (this.model.getObservable('alreadyAdded')()) {\n                this.resultBlockVisibility(true);\n            }\n            this.model.getObservable('additionalOptionsApplied').subscribe(function (value) {\n                if (value == true) { //eslint-disable-line eqeqeq\n                    self.resultBlockVisibility(true);\n                }\n            });\n        },\n\n        /**\n         * @param {String} key\n         * @return {*}\n         */\n        getObservable: function (key) {\n            return this.model.getObservable(key);\n        },\n\n        /**\n         * Hide\\Show form block\n         */\n        toggleFormBlockVisibility: function () {\n            if (!this.model.getObservable('alreadyAdded')()) {\n                this.formBlockVisibility(!this.formBlockVisibility());\n            } else {\n                this.resultBlockVisibility(!this.resultBlockVisibility());\n            }\n        },\n\n        /**\n         * Edit options\n         */\n        editOptions: function () {\n            this.resultBlockVisibility(false);\n            this.formBlockVisibility(true);\n        },\n\n        /**\n         * Delete options\n         */\n        deleteOptions: function () {\n            giftOptionsService(this.model, true);\n        },\n\n        /**\n         * Hide form block\n         */\n        hideFormBlock: function () {\n            this.formBlockVisibility(false);\n\n            if (this.model.getObservable('alreadyAdded')()) {\n                this.resultBlockVisibility(true);\n            }\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        hasActiveOptions: function () {\n            var regionData = this.getRegion('additionalOptions'),\n                options = regionData(),\n                i;\n\n            for (i = 0; i < options.length; i++) {\n                if (options[i].isActive()) {\n                    return true;\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isActive: function () {\n            return this.model.isGiftMessageAvailable();\n        },\n\n        /**\n         * Submit options\n         */\n        submitOptions: function () {\n            giftOptionsService(this.model);\n        }\n    });\n});\n","Magento_GiftMessage/js/model/gift-options.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'ko'\n], function (_, ko) {\n    'use strict';\n\n    return {\n        options: ko.observableArray([]),\n\n        /**\n         * @param {Object} option\n         */\n        addOption: function (option) {\n            if (!this.options().hasOwnProperty(option.itemId)) {\n                this.options.push({\n                        id: option.itemId, value: option\n                    }\n                );\n            }\n        },\n\n        /**\n         * @param {*} itemId\n         * @return {*}\n         */\n        getOptionByItemId: function (itemId) {\n            var option = null;\n\n            _.each(this.options(), function (data) {\n                if (data.id === itemId) {\n                    option = data.value;\n\n                    return false;\n                }\n            });\n\n            return option;\n        }\n    };\n});\n","Magento_GiftMessage/js/model/gift-message.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'uiElement',\n    'underscore',\n    'mage/url'\n], function (uiElement, _, url) {\n    'use strict';\n\n    var provider = uiElement();\n\n    return function (itemId) {\n        var model = {\n            id: 'message-' + itemId,\n            itemId: itemId,\n            observables: {},\n            additionalOptions: [],\n            submitParams: [\n                'recipient',\n                'sender',\n                'message'\n            ],\n\n            /**\n             * Initialize.\n             */\n            initialize: function () {\n                var message = false;\n\n                this.getObservable('alreadyAdded')(false);\n\n                if (this.itemId == 'orderLevel') { //eslint-disable-line eqeqeq\n                    message = window.giftOptionsConfig.giftMessage.hasOwnProperty(this.itemId) ?\n                        window.giftOptionsConfig.giftMessage[this.itemId] :\n                        null;\n                } else {\n                    message =\n                        window.giftOptionsConfig.giftMessage.hasOwnProperty('itemLevel') &&\n                        window.giftOptionsConfig.giftMessage.itemLevel.hasOwnProperty(this.itemId) ?\n                            window.giftOptionsConfig.giftMessage.itemLevel[this.itemId].message :\n                            null;\n                }\n\n                if (_.isObject(message)) {\n                    this.getObservable('recipient')(message.recipient);\n                    this.getObservable('sender')(message.sender);\n                    this.getObservable('message')(message.message);\n                    this.getObservable('alreadyAdded')(true);\n                }\n            },\n\n            /**\n             * @param {String} key\n             * @return {*}\n             */\n            getObservable: function (key) {\n                this.initObservable(this.id, key);\n\n                return provider[this.getUniqueKey(this.id, key)];\n            },\n\n            /**\n             * @param {String} node\n             * @param {String} key\n             */\n            initObservable: function (node, key) {\n                if (node && !this.observables.hasOwnProperty(node)) {\n                    this.observables[node] = [];\n                }\n\n                if (key && this.observables[node].indexOf(key) === -1) {\n                    this.observables[node].push(key);\n                    provider.observe(this.getUniqueKey(node, key));\n                }\n            },\n\n            /**\n             * @param {String} node\n             * @param {String} key\n             * @return {String}\n             */\n            getUniqueKey: function (node, key) {\n                return node + '-' + key;\n            },\n\n            /**\n             * @param {String} key\n             * @return {null}\n             */\n            getConfigValue: function (key) {\n                return window.giftOptionsConfig.hasOwnProperty(key) ?\n                    window.giftOptionsConfig[key]\n                    : null;\n            },\n\n            /**\n             * Reset.\n             */\n            reset: function () {\n                this.getObservable('isClear')(true);\n            },\n\n            /**\n             * @return {Array}\n             */\n            getAfterSubmitCallbacks: function () {\n                var callbacks = [];\n\n                callbacks.push(this.afterSubmit);\n                _.each(this.additionalOptions, function (option) {\n                    if (_.isFunction(option.afterSubmit)) {\n                        callbacks.push(option.afterSubmit);\n                    }\n                });\n\n                return callbacks;\n            },\n\n            /**\n             * After submit.\n             */\n            afterSubmit: function () {\n                window.location.href = url.build('checkout/cart/updatePost') +\n                    '?form_key=' + window.checkoutConfig.formKey +\n                    '&cart[]';\n            },\n\n            /**\n             * @param {Boolean} remove\n             * @return {Object}\n             */\n            getSubmitParams: function (remove) {\n                var params = {},\n                    self = this;\n\n                _.each(this.submitParams, function (key) {\n                    var observable = provider[self.getUniqueKey(self.id, key)];\n\n                    if (_.isFunction(observable)) {\n                        params[key] = remove ? null : observable();\n                    }\n                });\n\n                if (this.additionalOptions.length) {\n                    params['extension_attributes'] = {};\n                }\n                _.each(this.additionalOptions, function (option) {\n                    if (_.isFunction(option.getSubmitParams)) {\n                        params['extension_attributes'] = _.extend(\n                            params['extension_attributes'],\n                            option.getSubmitParams(remove)\n                        );\n                    }\n                });\n\n                return params;\n            },\n\n            /**\n             * Check if gift message can be displayed\n             *\n             * @returns {Boolean}\n             */\n            isGiftMessageAvailable: function () {\n                var isGloballyAvailable,\n                    giftMessageConfig,\n                    itemConfig;\n\n                // itemId represent gift message level: 'orderLevel' constant or cart item ID\n                if (this.itemId === 'orderLevel') {\n                    return this.getConfigValue('isOrderLevelGiftOptionsEnabled');\n                }\n\n                // gift message product configuration must override system configuration\n                isGloballyAvailable = this.getConfigValue('isItemLevelGiftOptionsEnabled');\n                giftMessageConfig = window.giftOptionsConfig.giftMessage;\n                itemConfig = giftMessageConfig.hasOwnProperty('itemLevel') &&\n                    giftMessageConfig.itemLevel.hasOwnProperty(this.itemId) ?\n                    giftMessageConfig.itemLevel[this.itemId] :\n                    {};\n\n                return itemConfig.hasOwnProperty('is_available') ? itemConfig['is_available'] : isGloballyAvailable;\n            }\n        };\n\n        model.initialize();\n\n        return model;\n    };\n});\n","Magento_GiftMessage/js/model/url-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Checkout/js/model/url-builder'\n], function ($, urlBuilder) {\n    'use strict';\n\n    return $.extend(urlBuilder, {\n        storeCode: window.giftOptionsConfig.storeCode\n    });\n});\n","Magento_Persistent/js/view/customer-data-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'mage/utils/wrapper'\n], function ($, wrapper) {\n    'use strict';\n\n    var mixin = {\n\n        /**\n         * Check if persistent section is expired due to lifetime.\n         *\n         * @param {Function} originFn - Original method.\n         * @return {Array}\n         */\n        getExpiredSectionNames: function (originFn) {\n            var expiredSections = originFn(),\n                storage = $.initNamespaceStorage('mage-cache-storage').localStorage,\n                currentTimestamp = Math.floor(Date.now() / 1000),\n                persistentIndex = expiredSections.indexOf('persistent'),\n                persistentLifeTime = 0,\n                sectionData;\n\n            if (window.persistent !== undefined && window.persistent.expirationLifetime !== undefined) {\n                persistentLifeTime = window.persistent.expirationLifetime;\n            }\n\n            if (persistentIndex !== -1) {\n                sectionData = storage.get('persistent');\n\n                if (typeof sectionData === 'object' &&\n                    sectionData['data_id'] + persistentLifeTime >= currentTimestamp\n                ) {\n                    expiredSections.splice(persistentIndex, 1);\n                }\n            }\n\n            return expiredSections;\n        },\n\n        /**\n         * @param {Object} settings\n         * @constructor\n         */\n        'Magento_Customer/js/customer-data': function (originFn) {\n            let mageCacheTimeout = new Date($.localStorage.get('mage-cache-timeout')),\n                mageCacheSessId = $.cookieStorage.isSet('mage-cache-sessid');\n\n            originFn();\n            if (window.persistent !== undefined && (mageCacheTimeout < new Date() || !mageCacheSessId)) {\n                this.reload(['persistent','cart'],true);\n            }\n        }\n    };\n\n    /**\n     * Override default customer-data.getExpiredSectionNames().\n     */\n    return function (target) {\n        return wrapper.extend(target, mixin);\n    };\n});\n","Magento_Persistent/js/view/additional-welcome.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/translate',\n    'Magento_Customer/js/customer-data'\n], function ($, $t, customerData) {\n    'use strict';\n\n    return {\n        /**\n         * Init.\n         */\n        init: function () {\n            var persistent = customerData.get('persistent');\n\n            if (persistent().fullname === undefined) {\n                customerData.get('persistent').subscribe(this.replacePersistentWelcome);\n            } else {\n                this.replacePersistentWelcome();\n            }\n        },\n\n        /**\n         * Replace welcome message for customer with persistent cookie.\n         */\n        replacePersistentWelcome: function () {\n            var persistent = customerData.get('persistent'),\n                welcomeElems;\n\n            if (persistent().fullname !== undefined) {\n                welcomeElems = $('li.greet.welcome > span.not-logged-in');\n\n                if (welcomeElems.length) {\n                    $(welcomeElems).each(function () {\n                        var html = $t('Welcome, %1!').replace('%1', persistent().fullname);\n\n                        $(this).attr('data-bind', html);\n                        $(this).html(html);\n                    });\n                    $(welcomeElems).append(' <span><a ' + window.notYouLink + '>' + $t('Not you?') + '</a>');\n                }\n            }\n        },\n\n        /**\n         * @constructor\n         */\n        'Magento_Persistent/js/view/additional-welcome': function () {\n            this.init();\n        }\n    };\n});\n","Magento_Sales/js/orders-returns.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.ordersReturns', {\n        options: {\n            zipCode: '#oar-zip', // Search by zip code.\n            emailAddress: '#oar-email', // Search by email address.\n            searchType: '#quick-search-type-id' // Search element used for choosing between the two.\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            $(this.options.searchType).on('change', $.proxy(this._showIdentifyBlock, this)).trigger('change');\n        },\n\n        /**\n         * Show either the search by zip code option or the search by email address option.\n         * @private\n         * @param {jQuery.Event} e - Change event. Event target value is either 'zip' or 'email'.\n         */\n        _showIdentifyBlock: function (e) {\n            var value = $(e.target).val();\n\n            $(this.options.zipCode).toggle(value === 'zip');\n            $(this.options.emailAddress).toggle(value === 'email');\n        }\n    });\n\n    return $.mage.ordersReturns;\n});\n","Magento_Sales/js/gift-message.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.giftMessage', {\n        options: {\n            rowPrefix: '#order-item-row-', // Selector prefix for item's row in the table.\n            linkPrefix: '#order-item-gift-message-link-', // Selector prefix for the 'Gift Message' link.\n            duration: 100, // Toggle duration.\n            expandedClass: 'expanded', // Class added/removed to/from the 'Gift Message' link.\n            expandedContentClass: 'expanded-content', // Class added/removed to/from the 'Gift Message' content.\n            lastClass: 'last' // Class added/removed to/from the last item's row in the products table.\n        },\n\n        /**\n         * Bind a click handler on the widget's element to toggle the gift message.\n         * @private\n         */\n        _create: function () {\n            this.element.on('click', $.proxy(this._toggleGiftMessage, this));\n        },\n\n        /**\n         * Toggle the display of the item's corresponding gift message.\n         * @private\n         * @param {jQuery.Event} event - Click event.\n         */\n        _toggleGiftMessage: function (event) {\n            var element = $(event.target), // Click target. The 'Gift Message' link or 'Close' button.\n                options = this.options, // Cached widget options.\n                itemId = element.data('item-id'), // The individual item's numeric id.\n                link = $(options.linkPrefix + itemId), // The 'Gift Message' expandable link.\n                row = $(options.rowPrefix + itemId), // The item's row in the products table.\n                region = $('#' + element.attr('aria-controls')); // The gift message container region.\n\n            region.toggleClass(options.expandedContentClass, options.duration, function () {\n                if (region.attr('aria-expanded') === 'true') {\n                    region.attr('aria-expanded', 'false');\n\n                    if (region.hasClass(options.lastClass)) {\n                        row.addClass(options.lastClass);\n                    }\n                } else {\n                    region.attr('aria-expanded', 'true');\n\n                    if (region.hasClass(options.lastClass)) {\n                        row.removeClass(options.lastClass);\n                    }\n                }\n                link.toggleClass(options.expandedClass);\n            });\n            event.preventDefault(); // Prevent event propagation and avoid going to the link's href.\n        }\n    });\n\n    return $.mage.giftMessage;\n});\n","Magento_Sales/js/view/last-ordered-items.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Customer/js/customer-data',\n    'underscore'\n], function (Component, customerData, _) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            isShowAddToCart: false\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super();\n            this.lastOrderedItems = customerData.get('last-ordered-items');\n            this.lastOrderedItems.subscribe(this.checkSalableItems.bind(this));\n            this.checkSalableItems();\n\n            return this;\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super()\n                .observe('isShowAddToCart');\n\n            return this;\n        },\n\n        /**\n         * Check if items is_saleable and change add to cart button visibility.\n         */\n        checkSalableItems: function () {\n            var isShowAddToCart = _.some(this.lastOrderedItems().items, {\n                'is_saleable': true\n            });\n\n            this.isShowAddToCart(isShowAddToCart);\n        }\n    });\n});\n","Magento_Fedex/js/view/shipping-rates-validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/shipping-rates-validator',\n    'Magento_Checkout/js/model/shipping-rates-validation-rules',\n    'Magento_Fedex/js/model/shipping-rates-validator',\n    'Magento_Fedex/js/model/shipping-rates-validation-rules'\n], function (\n    Component,\n    defaultShippingRatesValidator,\n    defaultShippingRatesValidationRules,\n    fedexShippingRatesValidator,\n    fedexShippingRatesValidationRules\n) {\n    'use strict';\n\n    defaultShippingRatesValidator.registerValidator('fedex', fedexShippingRatesValidator);\n    defaultShippingRatesValidationRules.registerRules('fedex', fedexShippingRatesValidationRules);\n\n    return Component;\n});\n","Magento_Fedex/js/model/shipping-rates-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mageUtils',\n    'Magento_Fedex/js/model/shipping-rates-validation-rules',\n    'mage/translate'\n], function ($, utils, validationRules, $t) {\n    'use strict';\n\n    return {\n        validationErrors: [],\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validate: function (address) {\n            var self = this;\n\n            this.validationErrors = [];\n            $.each(validationRules.getRules(), function (field, rule) {\n                var message;\n\n                if (rule.required && utils.isEmpty(address[field])) {\n                    message = $t('Field ') + field + $t(' is required.');\n\n                    self.validationErrors.push(message);\n                }\n            });\n\n            return !this.validationErrors.length;\n        }\n    };\n});\n","Magento_Fedex/js/model/shipping-rates-validation-rules.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return {\n                'postcode': {\n                    'required': true\n                },\n                'country_id': {\n                    'required': true\n                },\n                'city': {\n                    'required': true\n                }\n            };\n        }\n    };\n});\n","Torresani_SiWeGO/js/view/shipping-rates-validation.js":"/**\n * Copyright \u00a9 2015 Magento. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine(\n    [\n        'uiComponent',\n        'Magento_Checkout/js/model/shipping-rates-validator',\n        'Magento_Checkout/js/model/shipping-rates-validation-rules',\n        '../model/shipping-rates-validator',\n        '../model/shipping-rates-validation-rules'\n    ],\n    function (\n        Component,\n        defaultShippingRatesValidator,\n        defaultShippingRatesValidationRules,\n        siwegoShippingRatesValidator,\n        siwegoShippingRatesValidationRules\n    ) {\n        \"use strict\";\n        defaultShippingRatesValidator.registerValidator('siwego', siwegoShippingRatesValidator);\n        defaultShippingRatesValidationRules.registerRules('siwego', siwegoShippingRatesValidationRules);\n        return Component;\n    }\n);\n","Torresani_SiWeGO/js/model/shipping-rates-validator.js":"define(\n    [\n        'jquery',\n        'mageUtils',\n        './shipping-rates-validation-rules',\n        'mage/translate'\n    ],\n    function ($, utils, validationRules, $t) {\n        \"use strict\";\n        return {\n            validationErrors: [],\n            validate: function (address) {\n                var self = this;\n                this.validationErrors = [];\n                $.each(validationRules.getRules(), function (field, rule) {\n                    if (rule.required && utils.isEmpty(address[field])) {\n                        var message = $t('Field ') + field + $t(' is required.');\n                        self.validationErrors.push(message);\n                    }\n                });\n                return !Boolean(this.validationErrors.length);\n            }\n        };\n    }\n);","Torresani_SiWeGO/js/model/shipping-rates-validation-rules.js":"/**\n * Copyright \u00a9 2015 Magento. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*global define*/\ndefine(\n    [],\n    function () {\n        \"use strict\";\n        return {\n            getRules: function () {\n                return {\n                    'postcode': {\n                        'required': true\n                    },\n                    'country_id': {\n                        'required': true\n                    },\n                    'region_id' : {\n                        'required': false\n                    },\n                    'city' : {\n                        'required': false\n                    }\n                };\n            }\n        };\n    }\n);\n","Magento_LoginAsCustomerFrontendUi/js/login.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_Customer/js/customer-data',\n    'Magento_Customer/js/section-config'\n], function ($, customerData, sectionConfig) {\n\n    'use strict';\n\n    return function (config) {\n        customerData.reload(sectionConfig.getSectionNames()).done(function () {\n            window.location.href = config.redirectUrl;\n        });\n    };\n});\n","Magento_LoginAsCustomerFrontendUi/js/view/loginAsCustomer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'uiComponent',\n    'Magento_Customer/js/customer-data',\n    'mage/translate'\n], function ($, _, Component, customer) {\n    'use strict';\n\n    return Component.extend({\n\n        defaults: {\n            isVisible: false\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            var customerData, loggedAsCustomerData;\n\n            this._super();\n\n            customerData = customer.get('customer');\n            loggedAsCustomerData = customer.get('loggedAsCustomer');\n\n            customerData.subscribe(function (data) {\n                this.fullname = data.fullname;\n                this.updateBanner();\n            }.bind(this));\n            loggedAsCustomerData.subscribe(function (data) {\n                this.adminUserId = data.adminUserId;\n                this.websiteName = data.websiteName;\n                this.updateBanner();\n            }.bind(this));\n\n            this.fullname = customerData().fullname;\n            this.adminUserId = loggedAsCustomerData().adminUserId;\n            this.websiteName = loggedAsCustomerData().websiteName;\n\n            this.updateBanner();\n        },\n\n        /** @inheritdoc */\n        initObservable: function () {\n            this._super()\n                .observe(['isVisible', 'notificationText']);\n\n            return this;\n        },\n\n        /**\n         * Update banner area\n         *\n         * @returns void\n         */\n        updateBanner: function () {\n            if (this.adminUserId !== undefined) {\n                this.isVisible(this.adminUserId);\n            }\n\n            if (this.fullname !== undefined && this.websiteName !== undefined) {\n                this.notificationText($.mage.__('You are connected as <strong>%1</strong> on %2')\n                    .replace('%1', _.escape(this.fullname))\n                    .replace('%2', _.escape(this.websiteName)));\n            }\n        }\n    });\n});\n","Magento_PageBuilder/js/events.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['uiEvents'], function (uiEvents) {\n    'use strict';\n\n    return {\n\n        /**\n         * Calls callback when name event is triggered\n         *\n         * @param {String} events\n         * @param {Function} callback\n         * @param {Function} ns\n         * @return {Object}\n         */\n        on: function (events, callback, ns) {\n            uiEvents.on('pagebuilder:' + events, callback, 'pagebuilder:' + ns);\n\n            return this;\n        },\n\n        /**\n         * Removed callback from listening to target event\n         *\n         * @param {String} ns\n         * @return {Object}\n         */\n        off: function (ns) {\n            uiEvents.off('pagebuilder:' + ns);\n\n            return this;\n        },\n\n        /**\n         * Triggers event and executes all attached callbacks\n         *\n         * @param {String} name\n         * @param {any} args\n         * @returns {Boolean}\n         */\n        trigger: function (name, args) {\n            return uiEvents.trigger('pagebuilder:' + name, args);\n        }\n    };\n});\n","Magento_PageBuilder/js/widget-initializer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'underscore',\n    'jquery',\n    'mage/apply/main',\n    'Magento_Ui/js/lib/view/utils/dom-observer'\n], function (_, $, mage, domObserver) {\n    'use strict';\n\n    /**\n     * Initializes components assigned to HTML elements.\n     *\n     *\n     * @param {HTMLElement} el\n     * @param {Array} data\n     * @param {Object} breakpoints\n     * @param {Object} currentViewport\n     */\n    function initializeWidget(el, data, breakpoints, currentViewport) {\n        _.each(data, function (config, component) {\n            config = config || {};\n            config.breakpoints = breakpoints;\n            config.currentViewport = currentViewport;\n            mage.applyFor(el, config, component);\n        });\n    }\n\n    return function (data, contextElement) {\n        _.each(data.config, function (componentConfiguration, elementPath) {\n            domObserver.get(\n                elementPath,\n                function (element) {\n                    var $element = $(element);\n\n                    if (contextElement) {\n                        $element = $(contextElement).find(element);\n                    }\n\n                    if ($element.length) {\n                        initializeWidget($element, componentConfiguration, data.breakpoints, data.currentViewport);\n                    }\n                }\n            );\n        });\n    };\n});\n","Magento_PageBuilder/js/resource/slick/slick.js":"/*\n     _ _      _       _\n ___| (_) ___| | __  (_)___\n/ __| | |/ __| |/ /  | / __|\n\\__ \\ | | (__|   < _ | \\__ \\\n|___/_|_|\\___|_|\\_(_)/ |___/\n                   |__/\n\n Version: 1.9.0\n  Author: Ken Wheeler\n Website: http://kenwheeler.github.io\n    Docs: http://kenwheeler.github.io/slick\n    Repo: http://github.com/kenwheeler/slick\n  Issues: http://github.com/kenwheeler/slick/issues\n\n */\n/* global window, document, define, jQuery, setInterval, clearInterval */\n;(function(factory) {\n    'use strict';\n    if (typeof define === 'function' && define.amd) {\n        define(['jquery'], factory);\n    } else if (typeof exports !== 'undefined') {\n        module.exports = factory(require('jquery'));\n    } else {\n        factory(jQuery);\n    }\n\n}(function($) {\n    'use strict';\n    var Slick = window.Slick || {};\n\n    Slick = (function() {\n\n        var instanceUid = 0;\n\n        function Slick(element, settings) {\n\n            var _ = this, dataSettings;\n\n            _.defaults = {\n                accessibility: true,\n                adaptiveHeight: false,\n                appendArrows: $(element),\n                appendDots: $(element),\n                arrows: true,\n                asNavFor: null,\n                prevArrow: '<button class=\"slick-prev\" aria-label=\"Previous\" type=\"button\">Previous</button>',\n                nextArrow: '<button class=\"slick-next\" aria-label=\"Next\" type=\"button\">Next</button>',\n                autoplay: false,\n                autoplaySpeed: 3000,\n                centerMode: false,\n                centerPadding: '50px',\n                cssEase: 'ease',\n                customPaging: function(slider, i) {\n                    return $('<button type=\"button\" />').text(i + 1);\n                },\n                dots: false,\n                dotsClass: 'slick-dots',\n                draggable: true,\n                easing: 'linear',\n                edgeFriction: 0.35,\n                fade: false,\n                focusOnSelect: false,\n                focusOnChange: false,\n                infinite: true,\n                initialSlide: 0,\n                lazyLoad: 'ondemand',\n                mobileFirst: false,\n                pauseOnHover: true,\n                pauseOnFocus: true,\n                pauseOnDotsHover: false,\n                respondTo: 'window',\n                responsive: null,\n                rows: 1,\n                rtl: false,\n                slide: '',\n                slidesPerRow: 1,\n                slidesToShow: 1,\n                slidesToScroll: 1,\n                speed: 500,\n                swipe: true,\n                swipeToSlide: false,\n                touchMove: true,\n                touchThreshold: 5,\n                useCSS: true,\n                useTransform: true,\n                variableWidth: false,\n                vertical: false,\n                verticalSwiping: false,\n                waitForAnimate: true,\n                zIndex: 1000\n            };\n\n            _.initials = {\n                animating: false,\n                dragging: false,\n                autoPlayTimer: null,\n                currentDirection: 0,\n                currentLeft: null,\n                currentSlide: 0,\n                direction: 1,\n                $dots: null,\n                listWidth: null,\n                listHeight: null,\n                loadIndex: 0,\n                $nextArrow: null,\n                $prevArrow: null,\n                scrolling: false,\n                slideCount: null,\n                slideWidth: null,\n                $slideTrack: null,\n                $slides: null,\n                sliding: false,\n                slideOffset: 0,\n                swipeLeft: null,\n                swiping: false,\n                $list: null,\n                touchObject: {},\n                transformsEnabled: false,\n                unslicked: false\n            };\n\n            $.extend(_, _.initials);\n\n            _.activeBreakpoint = null;\n            _.animType = null;\n            _.animProp = null;\n            _.breakpoints = [];\n            _.breakpointSettings = [];\n            _.cssTransitions = false;\n            _.focussed = false;\n            _.interrupted = false;\n            _.hidden = 'hidden';\n            _.paused = true;\n            _.positionProp = null;\n            _.respondTo = null;\n            _.rowCount = 1;\n            _.shouldClick = true;\n            _.$slider = $(element);\n            _.$slidesCache = null;\n            _.transformType = null;\n            _.transitionType = null;\n            _.visibilityChange = 'visibilitychange';\n            _.windowWidth = 0;\n            _.windowTimer = null;\n\n            dataSettings = $(element).data('slick') || {};\n\n            _.options = $.extend({}, _.defaults, settings, dataSettings);\n\n            _.currentSlide = _.options.initialSlide;\n\n            _.originalSettings = _.options;\n\n            if (typeof document.mozHidden !== 'undefined') {\n                _.hidden = 'mozHidden';\n                _.visibilityChange = 'mozvisibilitychange';\n            } else if (typeof document.webkitHidden !== 'undefined') {\n                _.hidden = 'webkitHidden';\n                _.visibilityChange = 'webkitvisibilitychange';\n            }\n\n            _.autoPlay = $.proxy(_.autoPlay, _);\n            _.autoPlayClear = $.proxy(_.autoPlayClear, _);\n            _.autoPlayIterator = $.proxy(_.autoPlayIterator, _);\n            _.changeSlide = $.proxy(_.changeSlide, _);\n            _.clickHandler = $.proxy(_.clickHandler, _);\n            _.selectHandler = $.proxy(_.selectHandler, _);\n            _.setPosition = $.proxy(_.setPosition, _);\n            _.swipeHandler = $.proxy(_.swipeHandler, _);\n            _.dragHandler = $.proxy(_.dragHandler, _);\n            _.keyHandler = $.proxy(_.keyHandler, _);\n\n            _.instanceUid = instanceUid++;\n\n            // A simple way to check for HTML strings\n            // Strict HTML recognition (must start with <)\n            // Extracted from jQuery v1.11 source\n            _.htmlExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*)$/;\n\n\n            _.registerBreakpoints();\n            _.init(true);\n\n        }\n\n        return Slick;\n\n    }());\n\n    Slick.prototype.activateADA = function() {\n        var _ = this;\n\n        _.$slideTrack.find('.slick-active').attr({\n            'aria-hidden': 'false'\n        }).find('a, input, button, select').attr({\n            'tabindex': '0'\n        });\n\n    };\n\n    Slick.prototype.addSlide = Slick.prototype.slickAdd = function(markup, index, addBefore) {\n\n        var _ = this;\n\n        if (typeof(index) === 'boolean') {\n            addBefore = index;\n            index = null;\n        } else if (index < 0 || (index >= _.slideCount)) {\n            return false;\n        }\n\n        _.unload();\n\n        if (typeof(index) === 'number') {\n            if (index === 0 && _.$slides.length === 0) {\n                $(markup).appendTo(_.$slideTrack);\n            } else if (addBefore) {\n                $(markup).insertBefore(_.$slides.eq(index));\n            } else {\n                $(markup).insertAfter(_.$slides.eq(index));\n            }\n        } else {\n            if (addBefore === true) {\n                $(markup).prependTo(_.$slideTrack);\n            } else {\n                $(markup).appendTo(_.$slideTrack);\n            }\n        }\n\n        _.$slides = _.$slideTrack.children(this.options.slide);\n\n        _.$slideTrack.children(this.options.slide).detach();\n\n        _.$slideTrack.append(_.$slides);\n\n        _.$slides.each(function(index, element) {\n            $(element).attr('data-slick-index', index);\n        });\n\n        _.$slidesCache = _.$slides;\n\n        _.reinit();\n\n    };\n\n    Slick.prototype.animateHeight = function() {\n        var _ = this;\n        if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {\n            var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);\n            _.$list.animate({\n                height: targetHeight\n            }, _.options.speed);\n        }\n    };\n\n    Slick.prototype.animateSlide = function(targetLeft, callback) {\n\n        var animProps = {},\n            _ = this;\n\n        _.animateHeight();\n\n        if (_.options.rtl === true && _.options.vertical === false) {\n            targetLeft = -targetLeft;\n        }\n        if (_.transformsEnabled === false) {\n            if (_.options.vertical === false) {\n                _.$slideTrack.animate({\n                    left: targetLeft\n                }, _.options.speed, _.options.easing, callback);\n            } else {\n                _.$slideTrack.animate({\n                    top: targetLeft\n                }, _.options.speed, _.options.easing, callback);\n            }\n\n        } else {\n\n            if (_.cssTransitions === false) {\n                if (_.options.rtl === true) {\n                    _.currentLeft = -(_.currentLeft);\n                }\n                $({\n                    animStart: _.currentLeft\n                }).animate({\n                    animStart: targetLeft\n                }, {\n                    duration: _.options.speed,\n                    easing: _.options.easing,\n                    step: function(now) {\n                        now = Math.ceil(now);\n                        if (_.options.vertical === false) {\n                            animProps[_.animType] = 'translate(' +\n                                now + 'px, 0px)';\n                            _.$slideTrack.css(animProps);\n                        } else {\n                            animProps[_.animType] = 'translate(0px,' +\n                                now + 'px)';\n                            _.$slideTrack.css(animProps);\n                        }\n                    },\n                    complete: function() {\n                        if (callback) {\n                            callback.call();\n                        }\n                    }\n                });\n\n            } else {\n\n                _.applyTransition();\n                targetLeft = Math.ceil(targetLeft);\n\n                if (_.options.vertical === false) {\n                    animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)';\n                } else {\n                    animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)';\n                }\n                _.$slideTrack.css(animProps);\n\n                if (callback) {\n                    setTimeout(function() {\n\n                        _.disableTransition();\n\n                        callback.call();\n                    }, _.options.speed);\n                }\n\n            }\n\n        }\n\n    };\n\n    Slick.prototype.getNavTarget = function() {\n\n        var _ = this,\n            asNavFor = _.options.asNavFor;\n\n        if ( asNavFor && asNavFor !== null ) {\n            asNavFor = $(asNavFor).not(_.$slider);\n        }\n\n        return asNavFor;\n\n    };\n\n    Slick.prototype.asNavFor = function(index) {\n\n        var _ = this,\n            asNavFor = _.getNavTarget();\n\n        if ( asNavFor !== null && typeof asNavFor === 'object' ) {\n            asNavFor.each(function() {\n                var target = $(this).slick('getSlick');\n                if(!target.unslicked) {\n                    target.slideHandler(index, true);\n                }\n            });\n        }\n\n    };\n\n    Slick.prototype.applyTransition = function(slide) {\n\n        var _ = this,\n            transition = {};\n\n        if (_.options.fade === false) {\n            transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase;\n        } else {\n            transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase;\n        }\n\n        if (_.options.fade === false) {\n            _.$slideTrack.css(transition);\n        } else {\n            _.$slides.eq(slide).css(transition);\n        }\n\n    };\n\n    Slick.prototype.autoPlay = function() {\n\n        var _ = this;\n\n        _.autoPlayClear();\n\n        if ( _.slideCount > _.options.slidesToShow ) {\n            _.autoPlayTimer = setInterval( _.autoPlayIterator, _.options.autoplaySpeed );\n        }\n\n    };\n\n    Slick.prototype.autoPlayClear = function() {\n\n        var _ = this;\n\n        if (_.autoPlayTimer) {\n            clearInterval(_.autoPlayTimer);\n        }\n\n    };\n\n    Slick.prototype.autoPlayIterator = function() {\n\n        var _ = this,\n            slideTo = _.currentSlide + _.options.slidesToScroll;\n\n        if ( !_.paused && !_.interrupted && !_.focussed ) {\n\n            if ( _.options.infinite === false ) {\n\n                if ( _.direction === 1 && ( _.currentSlide + 1 ) === ( _.slideCount - 1 )) {\n                    _.direction = 0;\n                }\n\n                else if ( _.direction === 0 ) {\n\n                    slideTo = _.currentSlide - _.options.slidesToScroll;\n\n                    if ( _.currentSlide - 1 === 0 ) {\n                        _.direction = 1;\n                    }\n\n                }\n\n            }\n\n            _.slideHandler( slideTo );\n\n        }\n\n    };\n\n    Slick.prototype.buildArrows = function() {\n\n        var _ = this;\n\n        if (_.options.arrows === true ) {\n\n            _.$prevArrow = $(_.options.prevArrow).addClass('slick-arrow');\n            _.$nextArrow = $(_.options.nextArrow).addClass('slick-arrow');\n\n            if( _.slideCount > _.options.slidesToShow ) {\n\n                _.$prevArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex');\n                _.$nextArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex');\n\n                if (_.htmlExpr.test(_.options.prevArrow)) {\n                    _.$prevArrow.prependTo(_.options.appendArrows);\n                }\n\n                if (_.htmlExpr.test(_.options.nextArrow)) {\n                    _.$nextArrow.appendTo(_.options.appendArrows);\n                }\n\n                if (_.options.infinite !== true) {\n                    _.$prevArrow\n                        .addClass('slick-disabled')\n                        .attr('aria-disabled', 'true');\n                }\n\n            } else {\n\n                _.$prevArrow.add( _.$nextArrow )\n\n                    .addClass('slick-hidden')\n                    .attr({\n                        'aria-disabled': 'true',\n                        'tabindex': '-1'\n                    });\n\n            }\n\n        }\n\n    };\n\n    Slick.prototype.buildDots = function() {\n\n        var _ = this,\n            i, dot;\n\n        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {\n\n            _.$slider.addClass('slick-dotted');\n\n            dot = $('<ul />').addClass(_.options.dotsClass);\n\n            for (i = 0; i <= _.getDotCount(); i += 1) {\n                dot.append($('<li />').append(_.options.customPaging.call(this, _, i)));\n            }\n\n            _.$dots = dot.appendTo(_.options.appendDots);\n\n            _.$dots.find('li').first().addClass('slick-active');\n\n        }\n\n    };\n\n    Slick.prototype.buildOut = function() {\n\n        var _ = this;\n\n        _.$slides =\n            _.$slider\n                .children( _.options.slide + ':not(.slick-cloned)')\n                .addClass('slick-slide');\n\n        _.slideCount = _.$slides.length;\n\n        _.$slides.each(function(index, element) {\n            $(element)\n                .attr('data-slick-index', index)\n                .data('originalStyling', $(element).attr('style') || '');\n        });\n\n        _.$slider.addClass('slick-slider');\n\n        _.$slideTrack = (_.slideCount === 0) ?\n            $('<div class=\"slick-track\"/>').appendTo(_.$slider) :\n            _.$slides.wrapAll('<div class=\"slick-track\"/>').parent();\n\n        _.$list = _.$slideTrack.wrap(\n            '<div class=\"slick-list\"/>').parent();\n        _.$slideTrack.css('opacity', 0);\n\n        if (_.options.centerMode === true || _.options.swipeToSlide === true) {\n            _.options.slidesToScroll = 1;\n        }\n\n        $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading');\n\n        _.setupInfinite();\n\n        _.buildArrows();\n\n        _.buildDots();\n\n        _.updateDots();\n\n\n        _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);\n\n        if (_.options.draggable === true) {\n            _.$list.addClass('draggable');\n        }\n\n    };\n\n    Slick.prototype.buildRows = function() {\n\n        var _ = this, a, b, c, newSlides, numOfSlides, originalSlides,slidesPerSection;\n\n        newSlides = document.createDocumentFragment();\n        originalSlides = _.$slider.children();\n\n        if(_.options.rows > 0) {\n\n            slidesPerSection = _.options.slidesPerRow * _.options.rows;\n            numOfSlides = Math.ceil(\n                originalSlides.length / slidesPerSection\n            );\n\n            for(a = 0; a < numOfSlides; a++){\n                var slide = document.createElement('div');\n                for(b = 0; b < _.options.rows; b++) {\n                    var row = document.createElement('div');\n                    for(c = 0; c < _.options.slidesPerRow; c++) {\n                        var target = (a * slidesPerSection + ((b * _.options.slidesPerRow) + c));\n                        if (originalSlides.get(target)) {\n                            row.appendChild(originalSlides.get(target));\n                        }\n                    }\n                    slide.appendChild(row);\n                }\n                newSlides.appendChild(slide);\n            }\n\n            _.$slider.empty().append(newSlides);\n            _.$slider.children().children().children()\n                .css({\n                    'width':(100 / _.options.slidesPerRow) + '%',\n                    'display': 'inline-block'\n                });\n\n        }\n\n    };\n\n    Slick.prototype.checkResponsive = function(initial, forceUpdate) {\n\n        var _ = this,\n            breakpoint, targetBreakpoint, respondToWidth, triggerBreakpoint = false;\n        var sliderWidth = _.$slider.width();\n        var windowWidth = window.innerWidth || $(window).width();\n\n        if (_.respondTo === 'window') {\n            respondToWidth = windowWidth;\n        } else if (_.respondTo === 'slider') {\n            respondToWidth = sliderWidth;\n        } else if (_.respondTo === 'min') {\n            respondToWidth = Math.min(windowWidth, sliderWidth);\n        }\n\n        if ( _.options.responsive &&\n            _.options.responsive.length &&\n            _.options.responsive !== null) {\n\n            targetBreakpoint = null;\n\n            for (breakpoint in _.breakpoints) {\n                if (_.breakpoints.hasOwnProperty(breakpoint)) {\n                    if (_.originalSettings.mobileFirst === false) {\n                        if (respondToWidth < _.breakpoints[breakpoint]) {\n                            targetBreakpoint = _.breakpoints[breakpoint];\n                        }\n                    } else {\n                        if (respondToWidth > _.breakpoints[breakpoint]) {\n                            targetBreakpoint = _.breakpoints[breakpoint];\n                        }\n                    }\n                }\n            }\n\n            if (targetBreakpoint !== null) {\n                if (_.activeBreakpoint !== null) {\n                    if (targetBreakpoint !== _.activeBreakpoint || forceUpdate) {\n                        _.activeBreakpoint =\n                            targetBreakpoint;\n                        if (_.breakpointSettings[targetBreakpoint] === 'unslick') {\n                            _.unslick(targetBreakpoint);\n                        } else {\n                            _.options = $.extend({}, _.originalSettings,\n                                _.breakpointSettings[\n                                    targetBreakpoint]);\n                            if (initial === true) {\n                                _.currentSlide = _.options.initialSlide;\n                            }\n                            _.refresh(initial);\n                        }\n                        triggerBreakpoint = targetBreakpoint;\n                    }\n                } else {\n                    _.activeBreakpoint = targetBreakpoint;\n                    if (_.breakpointSettings[targetBreakpoint] === 'unslick') {\n                        _.unslick(targetBreakpoint);\n                    } else {\n                        _.options = $.extend({}, _.originalSettings,\n                            _.breakpointSettings[\n                                targetBreakpoint]);\n                        if (initial === true) {\n                            _.currentSlide = _.options.initialSlide;\n                        }\n                        _.refresh(initial);\n                    }\n                    triggerBreakpoint = targetBreakpoint;\n                }\n            } else {\n                if (_.activeBreakpoint !== null) {\n                    _.activeBreakpoint = null;\n                    _.options = _.originalSettings;\n                    if (initial === true) {\n                        _.currentSlide = _.options.initialSlide;\n                    }\n                    _.refresh(initial);\n                    triggerBreakpoint = targetBreakpoint;\n                }\n            }\n\n            // only trigger breakpoints during an actual break. not on initialize.\n            if( !initial && triggerBreakpoint !== false ) {\n                _.$slider.trigger('breakpoint', [_, triggerBreakpoint]);\n            }\n        }\n\n    };\n\n    Slick.prototype.changeSlide = function(event, dontAnimate) {\n\n        var _ = this,\n            $target = $(event.currentTarget),\n            indexOffset, slideOffset, unevenOffset;\n\n        // If target is a link, prevent default action.\n        if($target.is('a')) {\n            event.preventDefault();\n        }\n\n        // If target is not the <li> element (ie: a child), find the <li>.\n        if(!$target.is('li')) {\n            $target = $target.closest('li');\n        }\n\n        unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0);\n        indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll;\n\n        switch (event.data.message) {\n\n            case 'previous':\n                slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset;\n                if (_.slideCount > _.options.slidesToShow) {\n                    _.slideHandler(_.currentSlide - slideOffset, false, dontAnimate);\n                }\n                break;\n\n            case 'next':\n                slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset;\n                if (_.slideCount > _.options.slidesToShow) {\n                    _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate);\n                }\n                break;\n\n            case 'index':\n                var index = event.data.index === 0 ? 0 :\n                    event.data.index || $target.index() * _.options.slidesToScroll;\n\n                _.slideHandler(_.checkNavigable(index), false, dontAnimate);\n                $target.children().trigger('focus');\n                break;\n\n            default:\n                return;\n        }\n\n    };\n\n    Slick.prototype.checkNavigable = function(index) {\n\n        var _ = this,\n            navigables, prevNavigable;\n\n        navigables = _.getNavigableIndexes();\n        prevNavigable = 0;\n        if (index > navigables[navigables.length - 1]) {\n            index = navigables[navigables.length - 1];\n        } else {\n            for (var n in navigables) {\n                if (index < navigables[n]) {\n                    index = prevNavigable;\n                    break;\n                }\n                prevNavigable = navigables[n];\n            }\n        }\n\n        return index;\n    };\n\n    Slick.prototype.cleanUpEvents = function() {\n\n        var _ = this;\n\n        if (_.options.dots && _.$dots !== null) {\n\n            $('li', _.$dots)\n                .off('click.slick', _.changeSlide)\n                .off('mouseenter.slick', $.proxy(_.interrupt, _, true))\n                .off('mouseleave.slick', $.proxy(_.interrupt, _, false));\n\n            if (_.options.accessibility === true) {\n                _.$dots.off('keydown.slick', _.keyHandler);\n            }\n        }\n\n        _.$slider.off('focus.slick blur.slick');\n\n        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {\n            _.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide);\n            _.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide);\n\n            if (_.options.accessibility === true) {\n                _.$prevArrow && _.$prevArrow.off('keydown.slick', _.keyHandler);\n                _.$nextArrow && _.$nextArrow.off('keydown.slick', _.keyHandler);\n            }\n        }\n\n        _.$list.off('touchstart.slick mousedown.slick', _.swipeHandler);\n        _.$list.off('touchmove.slick mousemove.slick', _.swipeHandler);\n        _.$list.off('touchend.slick mouseup.slick', _.swipeHandler);\n        _.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler);\n\n        _.$list.off('click.slick', _.clickHandler);\n\n        $(document).off(_.visibilityChange, _.visibility);\n\n        _.cleanUpSlideEvents();\n\n        if (_.options.accessibility === true) {\n            _.$list.off('keydown.slick', _.keyHandler);\n        }\n\n        if (_.options.focusOnSelect === true) {\n            $(_.$slideTrack).children().off('click.slick', _.selectHandler);\n        }\n\n        $(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange);\n\n        $(window).off('resize.slick.slick-' + _.instanceUid, _.resize);\n\n        $('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault);\n\n        $(window).off('load.slick.slick-' + _.instanceUid, _.setPosition);\n\n    };\n\n    Slick.prototype.cleanUpSlideEvents = function() {\n\n        var _ = this;\n\n        _.$list.off('mouseenter.slick', $.proxy(_.interrupt, _, true));\n        _.$list.off('mouseleave.slick', $.proxy(_.interrupt, _, false));\n\n    };\n\n    Slick.prototype.cleanUpRows = function() {\n\n        var _ = this, originalSlides;\n\n        if(_.options.rows > 0) {\n            originalSlides = _.$slides.children().children();\n            originalSlides.removeAttr('style');\n            _.$slider.empty().append(originalSlides);\n        }\n\n    };\n\n    Slick.prototype.clickHandler = function(event) {\n\n        var _ = this;\n\n        if (_.shouldClick === false) {\n            event.stopImmediatePropagation();\n            event.stopPropagation();\n            event.preventDefault();\n        }\n\n    };\n\n    Slick.prototype.destroy = function(refresh) {\n\n        var _ = this;\n\n        _.autoPlayClear();\n\n        _.touchObject = {};\n\n        _.cleanUpEvents();\n\n        $('.slick-cloned', _.$slider).detach();\n\n        if (_.$dots) {\n            _.$dots.remove();\n        }\n\n        if ( _.$prevArrow && _.$prevArrow.length ) {\n\n            _.$prevArrow\n                .removeClass('slick-disabled slick-arrow slick-hidden')\n                .removeAttr('aria-hidden aria-disabled tabindex')\n                .css('display','');\n\n            if ( _.htmlExpr.test( _.options.prevArrow )) {\n                _.$prevArrow.remove();\n            }\n        }\n\n        if ( _.$nextArrow && _.$nextArrow.length ) {\n\n            _.$nextArrow\n                .removeClass('slick-disabled slick-arrow slick-hidden')\n                .removeAttr('aria-hidden aria-disabled tabindex')\n                .css('display','');\n\n            if ( _.htmlExpr.test( _.options.nextArrow )) {\n                _.$nextArrow.remove();\n            }\n        }\n\n\n        if (_.$slides) {\n\n            _.$slides\n                .removeClass('slick-slide slick-active slick-center slick-visible slick-current')\n                .removeAttr('aria-hidden')\n                .removeAttr('data-slick-index')\n                .each(function(){\n                    $(this).attr('style', $(this).data('originalStyling'));\n                });\n\n            _.$slideTrack.children(this.options.slide).detach();\n\n            _.$slideTrack.detach();\n\n            _.$list.detach();\n\n            _.$slider.append(_.$slides);\n        }\n\n        _.cleanUpRows();\n\n        _.$slider.removeClass('slick-slider');\n        _.$slider.removeClass('slick-initialized');\n        _.$slider.removeClass('slick-dotted');\n\n        _.unslicked = true;\n\n        if(!refresh) {\n            _.$slider.trigger('destroy', [_]);\n        }\n\n    };\n\n    Slick.prototype.disableTransition = function(slide) {\n\n        var _ = this,\n            transition = {};\n\n        transition[_.transitionType] = '';\n\n        if (_.options.fade === false) {\n            _.$slideTrack.css(transition);\n        } else {\n            _.$slides.eq(slide).css(transition);\n        }\n\n    };\n\n    Slick.prototype.fadeSlide = function(slideIndex, callback) {\n\n        var _ = this;\n\n        if (_.cssTransitions === false) {\n\n            _.$slides.eq(slideIndex).css({\n                zIndex: _.options.zIndex\n            });\n\n            _.$slides.eq(slideIndex).animate({\n                opacity: 1\n            }, _.options.speed, _.options.easing, callback);\n\n        } else {\n\n            _.applyTransition(slideIndex);\n\n            _.$slides.eq(slideIndex).css({\n                opacity: 1,\n                zIndex: _.options.zIndex\n            });\n\n            if (callback) {\n                setTimeout(function() {\n\n                    _.disableTransition(slideIndex);\n\n                    callback.call();\n                }, _.options.speed);\n            }\n\n        }\n\n    };\n\n    Slick.prototype.fadeSlideOut = function(slideIndex) {\n\n        var _ = this;\n\n        if (_.cssTransitions === false) {\n\n            _.$slides.eq(slideIndex).animate({\n                opacity: 0,\n                zIndex: _.options.zIndex - 2\n            }, _.options.speed, _.options.easing);\n\n        } else {\n\n            _.applyTransition(slideIndex);\n\n            _.$slides.eq(slideIndex).css({\n                opacity: 0,\n                zIndex: _.options.zIndex - 2\n            });\n\n        }\n\n    };\n\n    Slick.prototype.filterSlides = Slick.prototype.slickFilter = function(filter) {\n\n        var _ = this;\n\n        if (filter !== null) {\n\n            _.$slidesCache = _.$slides;\n\n            _.unload();\n\n            _.$slideTrack.children(this.options.slide).detach();\n\n            _.$slidesCache.filter(filter).appendTo(_.$slideTrack);\n\n            _.reinit();\n\n        }\n\n    };\n\n    Slick.prototype.focusHandler = function() {\n\n        var _ = this;\n\n        // If any child element receives focus within the slider we need to pause the autoplay\n        _.$slider\n            .off('focus.slick blur.slick')\n            .on(\n                'focus.slick',\n                '*',\n                function(event) {\n                    var $sf = $(this);\n\n                    setTimeout(function() {\n                        if( _.options.pauseOnFocus ) {\n                            if ($sf.is(':focus')) {\n                                _.focussed = true;\n                                _.autoPlay();\n                            }\n                        }\n                    }, 0);\n                }\n            ).on(\n                'blur.slick',\n                '*',\n                function(event) {\n                    var $sf = $(this);\n\n                    // When a blur occurs on any elements within the slider we become unfocused\n                    if( _.options.pauseOnFocus ) {\n                        _.focussed = false;\n                        _.autoPlay();\n                    }\n                }\n            );\n    };\n\n    Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function() {\n\n        var _ = this;\n        return _.currentSlide;\n\n    };\n\n    Slick.prototype.getDotCount = function() {\n\n        var _ = this;\n\n        var breakPoint = 0;\n        var counter = 0;\n        var pagerQty = 0;\n\n        if (_.options.infinite === true) {\n            if (_.slideCount <= _.options.slidesToShow) {\n                 ++pagerQty;\n            } else {\n                while (breakPoint < _.slideCount) {\n                    ++pagerQty;\n                    breakPoint = counter + _.options.slidesToScroll;\n                    counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;\n                }\n            }\n        } else if (_.options.centerMode === true) {\n            pagerQty = _.slideCount;\n        } else if(!_.options.asNavFor) {\n            pagerQty = 1 + Math.ceil((_.slideCount - _.options.slidesToShow) / _.options.slidesToScroll);\n        }else {\n            while (breakPoint < _.slideCount) {\n                ++pagerQty;\n                breakPoint = counter + _.options.slidesToScroll;\n                counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;\n            }\n        }\n\n        return pagerQty - 1;\n\n    };\n\n    Slick.prototype.getLeft = function(slideIndex) {\n\n        var _ = this,\n            targetLeft,\n            verticalHeight,\n            verticalOffset = 0,\n            targetSlide,\n            coef;\n\n        _.slideOffset = 0;\n        verticalHeight = _.$slides.first().outerHeight(true);\n\n        if (_.options.infinite === true) {\n            if (_.slideCount > _.options.slidesToShow) {\n                _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1;\n                coef = -1\n\n                if (_.options.vertical === true && _.options.centerMode === true) {\n                    if (_.options.slidesToShow === 2) {\n                        coef = -1.5;\n                    } else if (_.options.slidesToShow === 1) {\n                        coef = -2\n                    }\n                }\n                verticalOffset = (verticalHeight * _.options.slidesToShow) * coef;\n            }\n            if (_.slideCount % _.options.slidesToScroll !== 0) {\n                if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) {\n                    if (slideIndex > _.slideCount) {\n                        _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1;\n                        verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1;\n                    } else {\n                        _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1;\n                        verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1;\n                    }\n                }\n            }\n        } else {\n            if (slideIndex + _.options.slidesToShow > _.slideCount) {\n                _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth;\n                verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight;\n            }\n        }\n\n        if (_.slideCount <= _.options.slidesToShow) {\n            _.slideOffset = 0;\n            verticalOffset = 0;\n        }\n\n        if (_.options.centerMode === true && _.slideCount <= _.options.slidesToShow) {\n            _.slideOffset = ((_.slideWidth * Math.floor(_.options.slidesToShow)) / 2) - ((_.slideWidth * _.slideCount) / 2);\n        } else if (_.options.centerMode === true && _.options.infinite === true) {\n            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth;\n        } else if (_.options.centerMode === true) {\n            _.slideOffset = 0;\n            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2);\n        }\n\n        if (_.options.vertical === false) {\n            targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset;\n        } else {\n            targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset;\n        }\n\n        if (_.options.variableWidth === true) {\n\n            if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {\n                targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);\n            } else {\n                targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow);\n            }\n\n            if (_.options.rtl === true) {\n                if (targetSlide[0]) {\n                    targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;\n                } else {\n                    targetLeft =  0;\n                }\n            } else {\n                targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;\n            }\n\n            if (_.options.centerMode === true) {\n                if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {\n                    targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);\n                } else {\n                    targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1);\n                }\n\n                if (_.options.rtl === true) {\n                    if (targetSlide[0]) {\n                        targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;\n                    } else {\n                        targetLeft =  0;\n                    }\n                } else {\n                    targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;\n                }\n\n                targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2;\n            }\n        }\n\n        return targetLeft;\n\n    };\n\n    Slick.prototype.getOption = Slick.prototype.slickGetOption = function(option) {\n\n        var _ = this;\n\n        return _.options[option];\n\n    };\n\n    Slick.prototype.getNavigableIndexes = function() {\n\n        var _ = this,\n            breakPoint = 0,\n            counter = 0,\n            indexes = [],\n            max;\n\n        if (_.options.infinite === false) {\n            max = _.slideCount;\n        } else {\n            breakPoint = _.options.slidesToScroll * -1;\n            counter = _.options.slidesToScroll * -1;\n            max = _.slideCount * 2;\n        }\n\n        while (breakPoint < max) {\n            indexes.push(breakPoint);\n            breakPoint = counter + _.options.slidesToScroll;\n            counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;\n        }\n\n        return indexes;\n\n    };\n\n    Slick.prototype.getSlick = function() {\n\n        return this;\n\n    };\n\n    Slick.prototype.getSlideCount = function() {\n\n        var _ = this,\n            slidesTraversed, swipedSlide, swipeTarget, centerOffset;\n\n        centerOffset = _.options.centerMode === true ? Math.floor(_.$list.width() / 2) : 0;\n        swipeTarget = (_.swipeLeft * -1) + centerOffset;\n\n        if (_.options.swipeToSlide === true) {\n\n            _.$slideTrack.find('.slick-slide').each(function(index, slide) {\n\n                var slideOuterWidth, slideOffset, slideRightBoundary;\n                slideOuterWidth = $(slide).outerWidth();\n                slideOffset = slide.offsetLeft;\n                if (_.options.centerMode !== true) {\n                    slideOffset += (slideOuterWidth / 2);\n                }\n\n                slideRightBoundary = slideOffset + (slideOuterWidth);\n\n                if (swipeTarget < slideRightBoundary) {\n                    swipedSlide = slide;\n                    return false;\n                }\n            });\n\n            slidesTraversed = Math.abs($(swipedSlide).attr('data-slick-index') - _.currentSlide) || 1;\n\n            return slidesTraversed;\n\n        } else {\n            return _.options.slidesToScroll;\n        }\n\n    };\n\n    Slick.prototype.goTo = Slick.prototype.slickGoTo = function(slide, dontAnimate) {\n\n        var _ = this;\n\n        _.changeSlide({\n            data: {\n                message: 'index',\n                index: parseInt(slide)\n            }\n        }, dontAnimate);\n\n    };\n\n    Slick.prototype.init = function(creation) {\n\n        var _ = this;\n\n        if (!$(_.$slider).hasClass('slick-initialized')) {\n\n            $(_.$slider).addClass('slick-initialized');\n\n            _.buildRows();\n            _.buildOut();\n            _.setProps();\n            _.startLoad();\n            _.loadSlider();\n            _.initializeEvents();\n            _.updateArrows();\n            _.updateDots();\n            _.checkResponsive(true);\n            _.focusHandler();\n\n        }\n\n        if (creation) {\n            _.$slider.trigger('init', [_]);\n        }\n\n        if (_.options.accessibility === true) {\n            _.initADA();\n        }\n\n        if ( _.options.autoplay ) {\n\n            _.paused = false;\n            _.autoPlay();\n\n        }\n\n    };\n\n    Slick.prototype.initADA = function() {\n        var _ = this,\n                numDotGroups = Math.ceil(_.slideCount / _.options.slidesToShow),\n                tabControlIndexes = _.getNavigableIndexes().filter(function(val) {\n                    return (val >= 0) && (val < _.slideCount);\n                });\n\n        _.$slides.add(_.$slideTrack.find('.slick-cloned')).attr({\n            'aria-hidden': 'true',\n            'tabindex': '-1'\n        }).find('a, input, button, select').attr({\n            'tabindex': '-1'\n        });\n\n        if (_.$dots !== null) {\n            _.$slides.not(_.$slideTrack.find('.slick-cloned')).each(function(i) {\n                var slideControlIndex = tabControlIndexes.indexOf(i);\n\n                $(this).attr({\n                    'role': 'tabpanel',\n                    'id': 'slick-slide' + _.instanceUid + i,\n                    'tabindex': -1\n                });\n\n                if (slideControlIndex !== -1) {\n                   var ariaButtonControl = 'slick-slide-control' + _.instanceUid + slideControlIndex\n                   if ($('#' + ariaButtonControl).length) {\n                     $(this).attr({\n                         'aria-describedby': ariaButtonControl\n                     });\n                   }\n                }\n            });\n\n            _.$dots.attr('role', 'tablist').find('li').each(function(i) {\n                var mappedSlideIndex = tabControlIndexes[i];\n\n                $(this).attr({\n                    'role': 'presentation'\n                });\n\n                $(this).find('button').first().attr({\n                    'role': 'tab',\n                    'id': 'slick-slide-control' + _.instanceUid + i,\n                    'aria-controls': 'slick-slide' + _.instanceUid + mappedSlideIndex,\n                    'aria-label': (i + 1) + ' of ' + numDotGroups,\n                    'aria-selected': null,\n                    'tabindex': '-1'\n                });\n\n            }).eq(_.currentSlide).find('button').attr({\n                'aria-selected': 'true',\n                'tabindex': '0'\n            }).end();\n        }\n\n        for (var i=_.currentSlide, max=i+_.options.slidesToShow; i < max; i++) {\n          if (_.options.focusOnChange) {\n            _.$slides.eq(i).attr({'tabindex': '0'});\n          } else {\n            _.$slides.eq(i).removeAttr('tabindex');\n          }\n        }\n\n        _.activateADA();\n\n    };\n\n    Slick.prototype.initArrowEvents = function() {\n\n        var _ = this;\n\n        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {\n            _.$prevArrow\n               .off('click.slick')\n               .on('click.slick', {\n                    message: 'previous'\n               }, _.changeSlide);\n            _.$nextArrow\n               .off('click.slick')\n               .on('click.slick', {\n                    message: 'next'\n               }, _.changeSlide);\n\n            if (_.options.accessibility === true) {\n                _.$prevArrow.on('keydown.slick', _.keyHandler);\n                _.$nextArrow.on('keydown.slick', _.keyHandler);\n            }\n        }\n\n    };\n\n    Slick.prototype.initDotEvents = function() {\n\n        var _ = this;\n\n        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {\n            $('li', _.$dots).on('click.slick', {\n                message: 'index'\n            }, _.changeSlide);\n\n            if (_.options.accessibility === true) {\n                _.$dots.on('keydown.slick', _.keyHandler);\n            }\n        }\n\n        if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.slideCount > _.options.slidesToShow) {\n\n            $('li', _.$dots)\n                .on('mouseenter.slick', $.proxy(_.interrupt, _, true))\n                .on('mouseleave.slick', $.proxy(_.interrupt, _, false));\n\n        }\n\n    };\n\n    Slick.prototype.initSlideEvents = function() {\n\n        var _ = this;\n\n        if ( _.options.pauseOnHover ) {\n\n            _.$list.on('mouseenter.slick', $.proxy(_.interrupt, _, true));\n            _.$list.on('mouseleave.slick', $.proxy(_.interrupt, _, false));\n\n        }\n\n    };\n\n    Slick.prototype.initializeEvents = function() {\n\n        var _ = this;\n\n        _.initArrowEvents();\n\n        _.initDotEvents();\n        _.initSlideEvents();\n\n        _.$list.on('touchstart.slick mousedown.slick', {\n            action: 'start'\n        }, _.swipeHandler);\n        _.$list.on('touchmove.slick mousemove.slick', {\n            action: 'move'\n        }, _.swipeHandler);\n        _.$list.on('touchend.slick mouseup.slick', {\n            action: 'end'\n        }, _.swipeHandler);\n        _.$list.on('touchcancel.slick mouseleave.slick', {\n            action: 'end'\n        }, _.swipeHandler);\n\n        _.$list.on('click.slick', _.clickHandler);\n\n        $(document).on(_.visibilityChange, $.proxy(_.visibility, _));\n\n        if (_.options.accessibility === true) {\n            _.$list.on('keydown.slick', _.keyHandler);\n        }\n\n        if (_.options.focusOnSelect === true) {\n            $(_.$slideTrack).children().on('click.slick', _.selectHandler);\n        }\n\n        $(window).on('orientationchange.slick.slick-' + _.instanceUid, $.proxy(_.orientationChange, _));\n\n        $(window).on('resize.slick.slick-' + _.instanceUid, $.proxy(_.resize, _));\n\n        $('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault);\n\n        $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition);\n        $(_.setPosition);\n\n    };\n\n    Slick.prototype.initUI = function() {\n\n        var _ = this;\n\n        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {\n\n            _.$prevArrow.show();\n            _.$nextArrow.show();\n\n        }\n\n        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {\n\n            _.$dots.show();\n\n        }\n\n    };\n\n    Slick.prototype.keyHandler = function(event) {\n\n        var _ = this;\n         //Dont slide if the cursor is inside the form fields and arrow keys are pressed\n        if(!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) {\n            if (event.keyCode === 37 && _.options.accessibility === true) {\n                _.changeSlide({\n                    data: {\n                        message: _.options.rtl === true ? 'next' :  'previous'\n                    }\n                });\n            } else if (event.keyCode === 39 && _.options.accessibility === true) {\n                _.changeSlide({\n                    data: {\n                        message: _.options.rtl === true ? 'previous' : 'next'\n                    }\n                });\n            }\n        }\n\n    };\n\n    Slick.prototype.lazyLoad = function() {\n\n        var _ = this,\n            loadRange, cloneRange, rangeStart, rangeEnd;\n\n        function loadImages(imagesScope) {\n\n            $('img[data-lazy]', imagesScope).each(function() {\n\n                var image = $(this),\n                    imageSource = $(this).attr('data-lazy'),\n                    imageSrcSet = $(this).attr('data-srcset'),\n                    imageSizes  = $(this).attr('data-sizes') || _.$slider.attr('data-sizes'),\n                    imageToLoad = document.createElement('img');\n\n                imageToLoad.onload = function() {\n\n                    image\n                        .animate({ opacity: 0 }, 100, function() {\n\n                            if (imageSrcSet) {\n                                image\n                                    .attr('srcset', imageSrcSet );\n\n                                if (imageSizes) {\n                                    image\n                                        .attr('sizes', imageSizes );\n                                }\n                            }\n\n                            image\n                                .attr('src', imageSource)\n                                .animate({ opacity: 1 }, 200, function() {\n                                    image\n                                        .removeAttr('data-lazy data-srcset data-sizes')\n                                        .removeClass('slick-loading');\n                                });\n                            _.$slider.trigger('lazyLoaded', [_, image, imageSource]);\n                        });\n\n                };\n\n                imageToLoad.onerror = function() {\n\n                    image\n                        .removeAttr( 'data-lazy' )\n                        .removeClass( 'slick-loading' )\n                        .addClass( 'slick-lazyload-error' );\n\n                    _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]);\n\n                };\n\n                imageToLoad.src = imageSource;\n\n            });\n\n        }\n\n        if (_.options.centerMode === true) {\n            if (_.options.infinite === true) {\n                rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1);\n                rangeEnd = rangeStart + _.options.slidesToShow + 2;\n            } else {\n                rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1));\n                rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide;\n            }\n        } else {\n            rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide;\n            rangeEnd = Math.ceil(rangeStart + _.options.slidesToShow);\n            if (_.options.fade === true) {\n                if (rangeStart > 0) rangeStart--;\n                if (rangeEnd <= _.slideCount) rangeEnd++;\n            }\n        }\n\n        loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd);\n\n        if (_.options.lazyLoad === 'anticipated') {\n            var prevSlide = rangeStart - 1,\n                nextSlide = rangeEnd,\n                $slides = _.$slider.find('.slick-slide');\n\n            for (var i = 0; i < _.options.slidesToScroll; i++) {\n                if (prevSlide < 0) prevSlide = _.slideCount - 1;\n                loadRange = loadRange.add($slides.eq(prevSlide));\n                loadRange = loadRange.add($slides.eq(nextSlide));\n                prevSlide--;\n                nextSlide++;\n            }\n        }\n\n        loadImages(loadRange);\n\n        if (_.slideCount <= _.options.slidesToShow) {\n            cloneRange = _.$slider.find('.slick-slide');\n            loadImages(cloneRange);\n        } else\n        if (_.currentSlide >= _.slideCount - _.options.slidesToShow) {\n            cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow);\n            loadImages(cloneRange);\n        } else if (_.currentSlide === 0) {\n            cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1);\n            loadImages(cloneRange);\n        }\n\n    };\n\n    Slick.prototype.loadSlider = function() {\n\n        var _ = this;\n\n        _.setPosition();\n\n        _.$slideTrack.css({\n            opacity: 1\n        });\n\n        _.$slider.removeClass('slick-loading');\n\n        _.initUI();\n\n        if (_.options.lazyLoad === 'progressive') {\n            _.progressiveLazyLoad();\n        }\n\n    };\n\n    Slick.prototype.next = Slick.prototype.slickNext = function() {\n\n        var _ = this;\n\n        _.changeSlide({\n            data: {\n                message: 'next'\n            }\n        });\n\n    };\n\n    Slick.prototype.orientationChange = function() {\n\n        var _ = this;\n\n        _.checkResponsive();\n        _.setPosition();\n\n    };\n\n    Slick.prototype.pause = Slick.prototype.slickPause = function() {\n\n        var _ = this;\n\n        _.autoPlayClear();\n        _.paused = true;\n\n    };\n\n    Slick.prototype.play = Slick.prototype.slickPlay = function() {\n\n        var _ = this;\n\n        _.autoPlay();\n        _.options.autoplay = true;\n        _.paused = false;\n        _.focussed = false;\n        _.interrupted = false;\n\n    };\n\n    Slick.prototype.postSlide = function(index) {\n\n        var _ = this;\n\n        if( !_.unslicked ) {\n\n            _.$slider.trigger('afterChange', [_, index]);\n\n            _.animating = false;\n\n            if (_.slideCount > _.options.slidesToShow) {\n                _.setPosition();\n            }\n\n            _.swipeLeft = null;\n\n            if ( _.options.autoplay ) {\n                _.autoPlay();\n            }\n\n            if (_.options.accessibility === true) {\n                _.initADA();\n\n                if (_.options.focusOnChange) {\n                    var $currentSlide = $(_.$slides.get(_.currentSlide));\n                    $currentSlide.attr('tabindex', 0).focus();\n                }\n            }\n\n        }\n\n    };\n\n    Slick.prototype.prev = Slick.prototype.slickPrev = function() {\n\n        var _ = this;\n\n        _.changeSlide({\n            data: {\n                message: 'previous'\n            }\n        });\n\n    };\n\n    Slick.prototype.preventDefault = function(event) {\n\n        event.preventDefault();\n\n    };\n\n    Slick.prototype.progressiveLazyLoad = function( tryCount ) {\n\n        tryCount = tryCount || 1;\n\n        var _ = this,\n            $imgsToLoad = $( 'img[data-lazy]', _.$slider ),\n            image,\n            imageSource,\n            imageSrcSet,\n            imageSizes,\n            imageToLoad;\n\n        if ( $imgsToLoad.length ) {\n\n            image = $imgsToLoad.first();\n            imageSource = image.attr('data-lazy');\n            imageSrcSet = image.attr('data-srcset');\n            imageSizes  = image.attr('data-sizes') || _.$slider.attr('data-sizes');\n            imageToLoad = document.createElement('img');\n\n            imageToLoad.onload = function() {\n\n                if (imageSrcSet) {\n                    image\n                        .attr('srcset', imageSrcSet );\n\n                    if (imageSizes) {\n                        image\n                            .attr('sizes', imageSizes );\n                    }\n                }\n\n                image\n                    .attr( 'src', imageSource )\n                    .removeAttr('data-lazy data-srcset data-sizes')\n                    .removeClass('slick-loading');\n\n                if ( _.options.adaptiveHeight === true ) {\n                    _.setPosition();\n                }\n\n                _.$slider.trigger('lazyLoaded', [ _, image, imageSource ]);\n                _.progressiveLazyLoad();\n\n            };\n\n            imageToLoad.onerror = function() {\n\n                if ( tryCount < 3 ) {\n\n                    /**\n                     * try to load the image 3 times,\n                     * leave a slight delay so we don't get\n                     * servers blocking the request.\n                     */\n                    setTimeout( function() {\n                        _.progressiveLazyLoad( tryCount + 1 );\n                    }, 500 );\n\n                } else {\n\n                    image\n                        .removeAttr( 'data-lazy' )\n                        .removeClass( 'slick-loading' )\n                        .addClass( 'slick-lazyload-error' );\n\n                    _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]);\n\n                    _.progressiveLazyLoad();\n\n                }\n\n            };\n\n            imageToLoad.src = imageSource;\n\n        } else {\n\n            _.$slider.trigger('allImagesLoaded', [ _ ]);\n\n        }\n\n    };\n\n    Slick.prototype.refresh = function( initializing ) {\n\n        var _ = this, currentSlide, lastVisibleIndex;\n\n        lastVisibleIndex = _.slideCount - _.options.slidesToShow;\n\n        // in non-infinite sliders, we don't want to go past the\n        // last visible index.\n        if( !_.options.infinite && ( _.currentSlide > lastVisibleIndex )) {\n            _.currentSlide = lastVisibleIndex;\n        }\n\n        // if less slides than to show, go to start.\n        if ( _.slideCount <= _.options.slidesToShow ) {\n            _.currentSlide = 0;\n\n        }\n\n        currentSlide = _.currentSlide;\n\n        _.destroy(true);\n\n        $.extend(_, _.initials, { currentSlide: currentSlide });\n\n        _.init();\n\n        if( !initializing ) {\n\n            _.changeSlide({\n                data: {\n                    message: 'index',\n                    index: currentSlide\n                }\n            }, false);\n\n        }\n\n    };\n\n    Slick.prototype.registerBreakpoints = function() {\n\n        var _ = this, breakpoint, currentBreakpoint, l,\n            responsiveSettings = _.options.responsive || null;\n\n        if ( $.type(responsiveSettings) === 'array' && responsiveSettings.length ) {\n\n            _.respondTo = _.options.respondTo || 'window';\n\n            for ( breakpoint in responsiveSettings ) {\n\n                l = _.breakpoints.length-1;\n\n                if (responsiveSettings.hasOwnProperty(breakpoint)) {\n                    currentBreakpoint = responsiveSettings[breakpoint].breakpoint;\n\n                    // loop through the breakpoints and cut out any existing\n                    // ones with the same breakpoint number, we don't want dupes.\n                    while( l >= 0 ) {\n                        if( _.breakpoints[l] && _.breakpoints[l] === currentBreakpoint ) {\n                            _.breakpoints.splice(l,1);\n                        }\n                        l--;\n                    }\n\n                    _.breakpoints.push(currentBreakpoint);\n                    _.breakpointSettings[currentBreakpoint] = responsiveSettings[breakpoint].settings;\n\n                }\n\n            }\n\n            _.breakpoints.sort(function(a, b) {\n                return ( _.options.mobileFirst ) ? a-b : b-a;\n            });\n\n        }\n\n    };\n\n    Slick.prototype.reinit = function() {\n\n        var _ = this;\n\n        _.$slides =\n            _.$slideTrack\n                .children(_.options.slide)\n                .addClass('slick-slide');\n\n        _.slideCount = _.$slides.length;\n\n        if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) {\n            _.currentSlide = _.currentSlide - _.options.slidesToScroll;\n        }\n\n        if (_.slideCount <= _.options.slidesToShow) {\n            _.currentSlide = 0;\n        }\n\n        _.registerBreakpoints();\n\n        _.setProps();\n        _.setupInfinite();\n        _.buildArrows();\n        _.updateArrows();\n        _.initArrowEvents();\n        _.buildDots();\n        _.updateDots();\n        _.initDotEvents();\n        _.cleanUpSlideEvents();\n        _.initSlideEvents();\n\n        _.checkResponsive(false, true);\n\n        if (_.options.focusOnSelect === true) {\n            $(_.$slideTrack).children().on('click.slick', _.selectHandler);\n        }\n\n        _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);\n\n        _.setPosition();\n        _.focusHandler();\n\n        _.paused = !_.options.autoplay;\n        _.autoPlay();\n\n        _.$slider.trigger('reInit', [_]);\n\n    };\n\n    Slick.prototype.resize = function() {\n\n        var _ = this;\n\n        if ($(window).width() !== _.windowWidth) {\n            clearTimeout(_.windowDelay);\n            _.windowDelay = window.setTimeout(function() {\n                _.windowWidth = $(window).width();\n                _.checkResponsive();\n                if( !_.unslicked ) { _.setPosition(); }\n            }, 50);\n        }\n    };\n\n    Slick.prototype.removeSlide = Slick.prototype.slickRemove = function(index, removeBefore, removeAll) {\n\n        var _ = this;\n\n        if (typeof(index) === 'boolean') {\n            removeBefore = index;\n            index = removeBefore === true ? 0 : _.slideCount - 1;\n        } else {\n            index = removeBefore === true ? --index : index;\n        }\n\n        if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) {\n            return false;\n        }\n\n        _.unload();\n\n        if (removeAll === true) {\n            _.$slideTrack.children().remove();\n        } else {\n            _.$slideTrack.children(this.options.slide).eq(index).remove();\n        }\n\n        _.$slides = _.$slideTrack.children(this.options.slide);\n\n        _.$slideTrack.children(this.options.slide).detach();\n\n        _.$slideTrack.append(_.$slides);\n\n        _.$slidesCache = _.$slides;\n\n        _.reinit();\n\n    };\n\n    Slick.prototype.setCSS = function(position) {\n\n        var _ = this,\n            positionProps = {},\n            x, y;\n\n        if (_.options.rtl === true) {\n            position = -position;\n        }\n        x = _.positionProp == 'left' ? Math.ceil(position) + 'px' : '0px';\n        y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px';\n\n        positionProps[_.positionProp] = position;\n\n        if (_.transformsEnabled === false) {\n            _.$slideTrack.css(positionProps);\n        } else {\n            positionProps = {};\n            if (_.cssTransitions === false) {\n                positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';\n                _.$slideTrack.css(positionProps);\n            } else {\n                positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)';\n                _.$slideTrack.css(positionProps);\n            }\n        }\n\n    };\n\n    Slick.prototype.setDimensions = function() {\n\n        var _ = this;\n\n        if (_.options.vertical === false) {\n            if (_.options.centerMode === true) {\n                _.$list.css({\n                    padding: ('0px ' + _.options.centerPadding)\n                });\n            }\n        } else {\n            _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow);\n            if (_.options.centerMode === true) {\n                _.$list.css({\n                    padding: (_.options.centerPadding + ' 0px')\n                });\n            }\n        }\n\n        _.listWidth = _.$list.width();\n        _.listHeight = _.$list.height();\n\n\n        if (_.options.vertical === false && _.options.variableWidth === false) {\n            _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow);\n            _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length)));\n\n        } else if (_.options.variableWidth === true) {\n            _.$slideTrack.width(5000 * _.slideCount);\n        } else {\n            _.slideWidth = Math.ceil(_.listWidth);\n            _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length)));\n        }\n\n        var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width();\n        if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset);\n\n    };\n\n    Slick.prototype.setFade = function() {\n\n        var _ = this,\n            targetLeft;\n\n        _.$slides.each(function(index, element) {\n            targetLeft = (_.slideWidth * index) * -1;\n            if (_.options.rtl === true) {\n                $(element).css({\n                    position: 'relative',\n                    right: targetLeft,\n                    top: 0,\n                    zIndex: _.options.zIndex - 2,\n                    opacity: 0\n                });\n            } else {\n                $(element).css({\n                    position: 'relative',\n                    left: targetLeft,\n                    top: 0,\n                    zIndex: _.options.zIndex - 2,\n                    opacity: 0\n                });\n            }\n        });\n\n        _.$slides.eq(_.currentSlide).css({\n            zIndex: _.options.zIndex - 1,\n            opacity: 1\n        });\n\n    };\n\n    Slick.prototype.setHeight = function() {\n\n        var _ = this;\n\n        if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {\n            var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);\n            _.$list.css('height', targetHeight);\n        }\n\n    };\n\n    Slick.prototype.setOption =\n    Slick.prototype.slickSetOption = function() {\n\n        /**\n         * accepts arguments in format of:\n         *\n         *  - for changing a single option's value:\n         *     .slick(\"setOption\", option, value, refresh )\n         *\n         *  - for changing a set of responsive options:\n         *     .slick(\"setOption\", 'responsive', [{}, ...], refresh )\n         *\n         *  - for updating multiple values at once (not responsive)\n         *     .slick(\"setOption\", { 'option': value, ... }, refresh )\n         */\n\n        var _ = this, l, item, option, value, refresh = false, type;\n\n        if( $.type( arguments[0] ) === 'object' ) {\n\n            option =  arguments[0];\n            refresh = arguments[1];\n            type = 'multiple';\n\n        } else if ( $.type( arguments[0] ) === 'string' ) {\n\n            option =  arguments[0];\n            value = arguments[1];\n            refresh = arguments[2];\n\n            if ( arguments[0] === 'responsive' && $.type( arguments[1] ) === 'array' ) {\n\n                type = 'responsive';\n\n            } else if ( typeof arguments[1] !== 'undefined' ) {\n\n                type = 'single';\n\n            }\n\n        }\n\n        if ( type === 'single' ) {\n\n            _.options[option] = value;\n\n\n        } else if ( type === 'multiple' ) {\n\n            $.each( option , function( opt, val ) {\n\n                _.options[opt] = val;\n\n            });\n\n\n        } else if ( type === 'responsive' ) {\n\n            for ( item in value ) {\n\n                if( $.type( _.options.responsive ) !== 'array' ) {\n\n                    _.options.responsive = [ value[item] ];\n\n                } else {\n\n                    l = _.options.responsive.length-1;\n\n                    // loop through the responsive object and splice out duplicates.\n                    while( l >= 0 ) {\n\n                        if( _.options.responsive[l].breakpoint === value[item].breakpoint ) {\n\n                            _.options.responsive.splice(l,1);\n\n                        }\n\n                        l--;\n\n                    }\n\n                    _.options.responsive.push( value[item] );\n\n                }\n\n            }\n\n        }\n\n        if ( refresh ) {\n\n            _.unload();\n            _.reinit();\n\n        }\n\n    };\n\n    Slick.prototype.setPosition = function() {\n\n        var _ = this;\n\n        _.setDimensions();\n\n        _.setHeight();\n\n        if (_.options.fade === false) {\n            _.setCSS(_.getLeft(_.currentSlide));\n        } else {\n            _.setFade();\n        }\n\n        _.$slider.trigger('setPosition', [_]);\n\n    };\n\n    Slick.prototype.setProps = function() {\n\n        var _ = this,\n            bodyStyle = document.body.style;\n\n        _.positionProp = _.options.vertical === true ? 'top' : 'left';\n\n        if (_.positionProp === 'top') {\n            _.$slider.addClass('slick-vertical');\n        } else {\n            _.$slider.removeClass('slick-vertical');\n        }\n\n        if (bodyStyle.WebkitTransition !== undefined ||\n            bodyStyle.MozTransition !== undefined ||\n            bodyStyle.msTransition !== undefined) {\n            if (_.options.useCSS === true) {\n                _.cssTransitions = true;\n            }\n        }\n\n        if ( _.options.fade ) {\n            if ( typeof _.options.zIndex === 'number' ) {\n                if( _.options.zIndex < 3 ) {\n                    _.options.zIndex = 3;\n                }\n            } else {\n                _.options.zIndex = _.defaults.zIndex;\n            }\n        }\n\n        if (bodyStyle.OTransform !== undefined) {\n            _.animType = 'OTransform';\n            _.transformType = '-o-transform';\n            _.transitionType = 'OTransition';\n            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;\n        }\n        if (bodyStyle.MozTransform !== undefined) {\n            _.animType = 'MozTransform';\n            _.transformType = '-moz-transform';\n            _.transitionType = 'MozTransition';\n            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false;\n        }\n        if (bodyStyle.webkitTransform !== undefined) {\n            _.animType = 'webkitTransform';\n            _.transformType = '-webkit-transform';\n            _.transitionType = 'webkitTransition';\n            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;\n        }\n        if (bodyStyle.msTransform !== undefined) {\n            _.animType = 'msTransform';\n            _.transformType = '-ms-transform';\n            _.transitionType = 'msTransition';\n            if (bodyStyle.msTransform === undefined) _.animType = false;\n        }\n        if (bodyStyle.transform !== undefined && _.animType !== false) {\n            _.animType = 'transform';\n            _.transformType = 'transform';\n            _.transitionType = 'transition';\n        }\n        _.transformsEnabled = _.options.useTransform && (_.animType !== null && _.animType !== false);\n    };\n\n\n    Slick.prototype.setSlideClasses = function(index) {\n\n        var _ = this,\n            centerOffset, allSlides, indexOffset, remainder;\n\n        allSlides = _.$slider\n            .find('.slick-slide')\n            .removeClass('slick-active slick-center slick-current')\n            .attr('aria-hidden', 'true');\n\n        _.$slides\n            .eq(index)\n            .addClass('slick-current');\n\n        if (_.options.centerMode === true) {\n\n            var evenCoef = _.options.slidesToShow % 2 === 0 ? 1 : 0;\n\n            centerOffset = Math.floor(_.options.slidesToShow / 2);\n\n            if (_.options.infinite === true) {\n\n                if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) {\n                    _.$slides\n                        .slice(index - centerOffset + evenCoef, index + centerOffset + 1)\n                        .addClass('slick-active')\n                        .attr('aria-hidden', 'false');\n\n                } else {\n\n                    indexOffset = _.options.slidesToShow + index;\n                    allSlides\n                        .slice(indexOffset - centerOffset + 1 + evenCoef, indexOffset + centerOffset + 2)\n                        .addClass('slick-active')\n                        .attr('aria-hidden', 'false');\n\n                }\n\n                if (index === 0) {\n\n                    allSlides\n                        .eq(allSlides.length - 1 - _.options.slidesToShow)\n                        .addClass('slick-center');\n\n                } else if (index === _.slideCount - 1) {\n\n                    allSlides\n                        .eq(_.options.slidesToShow)\n                        .addClass('slick-center');\n\n                }\n\n            }\n\n            _.$slides\n                .eq(index)\n                .addClass('slick-center');\n\n        } else {\n\n            if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) {\n\n                _.$slides\n                    .slice(index, index + _.options.slidesToShow)\n                    .addClass('slick-active')\n                    .attr('aria-hidden', 'false');\n\n            } else if (allSlides.length <= _.options.slidesToShow) {\n\n                allSlides\n                    .addClass('slick-active')\n                    .attr('aria-hidden', 'false');\n\n            } else {\n\n                remainder = _.slideCount % _.options.slidesToShow;\n                indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index;\n\n                if (_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) {\n\n                    allSlides\n                        .slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder)\n                        .addClass('slick-active')\n                        .attr('aria-hidden', 'false');\n\n                } else {\n\n                    allSlides\n                        .slice(indexOffset, indexOffset + _.options.slidesToShow)\n                        .addClass('slick-active')\n                        .attr('aria-hidden', 'false');\n\n                }\n\n            }\n\n        }\n\n        if (_.options.lazyLoad === 'ondemand' || _.options.lazyLoad === 'anticipated') {\n            _.lazyLoad();\n        }\n    };\n\n    Slick.prototype.setupInfinite = function() {\n\n        var _ = this,\n            i, slideIndex, infiniteCount;\n\n        if (_.options.fade === true) {\n            _.options.centerMode = false;\n        }\n\n        if (_.options.infinite === true && _.options.fade === false) {\n\n            slideIndex = null;\n\n            if (_.slideCount > _.options.slidesToShow) {\n\n                if (_.options.centerMode === true) {\n                    infiniteCount = _.options.slidesToShow + 1;\n                } else {\n                    infiniteCount = _.options.slidesToShow;\n                }\n\n                for (i = _.slideCount; i > (_.slideCount -\n                        infiniteCount); i -= 1) {\n                    slideIndex = i - 1;\n                    $(_.$slides[slideIndex]).clone(true).attr('id', '')\n                        .attr('data-slick-index', slideIndex - _.slideCount)\n                        .prependTo(_.$slideTrack).addClass('slick-cloned');\n                }\n                for (i = 0; i < infiniteCount  + _.slideCount; i += 1) {\n                    slideIndex = i;\n                    $(_.$slides[slideIndex]).clone(true).attr('id', '')\n                        .attr('data-slick-index', slideIndex + _.slideCount)\n                        .appendTo(_.$slideTrack).addClass('slick-cloned');\n                }\n                _.$slideTrack.find('.slick-cloned').find('[id]').each(function() {\n                    $(this).attr('id', '');\n                });\n\n            }\n\n        }\n\n    };\n\n    Slick.prototype.interrupt = function( toggle ) {\n\n        var _ = this;\n\n        if( !toggle ) {\n            _.autoPlay();\n        }\n        _.interrupted = toggle;\n\n    };\n\n    Slick.prototype.selectHandler = function(event) {\n\n        var _ = this;\n\n        var targetElement =\n            $(event.target).is('.slick-slide') ?\n                $(event.target) :\n                $(event.target).parents('.slick-slide');\n\n        var index = parseInt(targetElement.attr('data-slick-index'));\n\n        if (!index) index = 0;\n\n        if (_.slideCount <= _.options.slidesToShow) {\n\n            _.slideHandler(index, false, true);\n            return;\n\n        }\n\n        _.slideHandler(index);\n\n    };\n\n    Slick.prototype.slideHandler = function(index, sync, dontAnimate) {\n\n        var targetSlide, animSlide, oldSlide, slideLeft, targetLeft = null,\n            _ = this, navTarget;\n\n        sync = sync || false;\n\n        if (_.animating === true && _.options.waitForAnimate === true) {\n            return;\n        }\n\n        if (_.options.fade === true && _.currentSlide === index) {\n            return;\n        }\n\n        if (sync === false) {\n            _.asNavFor(index);\n        }\n\n        targetSlide = index;\n        targetLeft = _.getLeft(targetSlide);\n        slideLeft = _.getLeft(_.currentSlide);\n\n        _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft;\n\n        if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) {\n            if (_.options.fade === false) {\n                targetSlide = _.currentSlide;\n                if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) {\n                    _.animateSlide(slideLeft, function() {\n                        _.postSlide(targetSlide);\n                    });\n                } else {\n                    _.postSlide(targetSlide);\n                }\n            }\n            return;\n        } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) {\n            if (_.options.fade === false) {\n                targetSlide = _.currentSlide;\n                if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) {\n                    _.animateSlide(slideLeft, function() {\n                        _.postSlide(targetSlide);\n                    });\n                } else {\n                    _.postSlide(targetSlide);\n                }\n            }\n            return;\n        }\n\n        if ( _.options.autoplay ) {\n            clearInterval(_.autoPlayTimer);\n        }\n\n        if (targetSlide < 0) {\n            if (_.slideCount % _.options.slidesToScroll !== 0) {\n                animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll);\n            } else {\n                animSlide = _.slideCount + targetSlide;\n            }\n        } else if (targetSlide >= _.slideCount) {\n            if (_.slideCount % _.options.slidesToScroll !== 0) {\n                animSlide = 0;\n            } else {\n                animSlide = targetSlide - _.slideCount;\n            }\n        } else {\n            animSlide = targetSlide;\n        }\n\n        _.animating = true;\n\n        _.$slider.trigger('beforeChange', [_, _.currentSlide, animSlide]);\n\n        oldSlide = _.currentSlide;\n        _.currentSlide = animSlide;\n\n        _.setSlideClasses(_.currentSlide);\n\n        if ( _.options.asNavFor ) {\n\n            navTarget = _.getNavTarget();\n            navTarget = navTarget.slick('getSlick');\n\n            if ( navTarget.slideCount <= navTarget.options.slidesToShow ) {\n                navTarget.setSlideClasses(_.currentSlide);\n            }\n\n        }\n\n        _.updateDots();\n        _.updateArrows();\n\n        if (_.options.fade === true) {\n            if (dontAnimate !== true) {\n\n                _.fadeSlideOut(oldSlide);\n\n                _.fadeSlide(animSlide, function() {\n                    _.postSlide(animSlide);\n                });\n\n            } else {\n                _.postSlide(animSlide);\n            }\n            _.animateHeight();\n            return;\n        }\n\n        if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) {\n            _.animateSlide(targetLeft, function() {\n                _.postSlide(animSlide);\n            });\n        } else {\n            _.postSlide(animSlide);\n        }\n\n    };\n\n    Slick.prototype.startLoad = function() {\n\n        var _ = this;\n\n        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {\n\n            _.$prevArrow.hide();\n            _.$nextArrow.hide();\n\n        }\n\n        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {\n\n            _.$dots.hide();\n\n        }\n\n        _.$slider.addClass('slick-loading');\n\n    };\n\n    Slick.prototype.swipeDirection = function() {\n\n        var xDist, yDist, r, swipeAngle, _ = this;\n\n        xDist = _.touchObject.startX - _.touchObject.curX;\n        yDist = _.touchObject.startY - _.touchObject.curY;\n        r = Math.atan2(yDist, xDist);\n\n        swipeAngle = Math.round(r * 180 / Math.PI);\n        if (swipeAngle < 0) {\n            swipeAngle = 360 - Math.abs(swipeAngle);\n        }\n\n        if ((swipeAngle <= 45) && (swipeAngle >= 0)) {\n            return (_.options.rtl === false ? 'left' : 'right');\n        }\n        if ((swipeAngle <= 360) && (swipeAngle >= 315)) {\n            return (_.options.rtl === false ? 'left' : 'right');\n        }\n        if ((swipeAngle >= 135) && (swipeAngle <= 225)) {\n            return (_.options.rtl === false ? 'right' : 'left');\n        }\n        if (_.options.verticalSwiping === true) {\n            if ((swipeAngle >= 35) && (swipeAngle <= 135)) {\n                return 'down';\n            } else {\n                return 'up';\n            }\n        }\n\n        return 'vertical';\n\n    };\n\n    Slick.prototype.swipeEnd = function(event) {\n\n        var _ = this,\n            slideCount,\n            direction;\n\n        _.dragging = false;\n        _.swiping = false;\n\n        if (_.scrolling) {\n            _.scrolling = false;\n            return false;\n        }\n\n        _.interrupted = false;\n        _.shouldClick = ( _.touchObject.swipeLength > 10 ) ? false : true;\n\n        if ( _.touchObject.curX === undefined ) {\n            return false;\n        }\n\n        if ( _.touchObject.edgeHit === true ) {\n            _.$slider.trigger('edge', [_, _.swipeDirection() ]);\n        }\n\n        if ( _.touchObject.swipeLength >= _.touchObject.minSwipe ) {\n\n            direction = _.swipeDirection();\n\n            switch ( direction ) {\n\n                case 'left':\n                case 'down':\n\n                    slideCount =\n                        _.options.swipeToSlide ?\n                            _.checkNavigable( _.currentSlide + _.getSlideCount() ) :\n                            _.currentSlide + _.getSlideCount();\n\n                    _.currentDirection = 0;\n\n                    break;\n\n                case 'right':\n                case 'up':\n\n                    slideCount =\n                        _.options.swipeToSlide ?\n                            _.checkNavigable( _.currentSlide - _.getSlideCount() ) :\n                            _.currentSlide - _.getSlideCount();\n\n                    _.currentDirection = 1;\n\n                    break;\n\n                default:\n\n\n            }\n\n            if( direction != 'vertical' ) {\n\n                _.slideHandler( slideCount );\n                _.touchObject = {};\n                _.$slider.trigger('swipe', [_, direction ]);\n\n            }\n\n        } else {\n\n            if ( _.touchObject.startX !== _.touchObject.curX ) {\n\n                _.slideHandler( _.currentSlide );\n                _.touchObject = {};\n\n            }\n\n        }\n\n    };\n\n    Slick.prototype.swipeHandler = function(event) {\n\n        var _ = this;\n\n        if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) {\n            return;\n        } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) {\n            return;\n        }\n\n        _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ?\n            event.originalEvent.touches.length : 1;\n\n        _.touchObject.minSwipe = _.listWidth / _.options\n            .touchThreshold;\n\n        if (_.options.verticalSwiping === true) {\n            _.touchObject.minSwipe = _.listHeight / _.options\n                .touchThreshold;\n        }\n\n        switch (event.data.action) {\n\n            case 'start':\n                _.swipeStart(event);\n                break;\n\n            case 'move':\n                _.swipeMove(event);\n                break;\n\n            case 'end':\n                _.swipeEnd(event);\n                break;\n\n        }\n\n    };\n\n    Slick.prototype.swipeMove = function(event) {\n\n        var _ = this,\n            edgeWasHit = false,\n            curLeft, swipeDirection, swipeLength, positionOffset, touches, verticalSwipeLength;\n\n        touches = event.originalEvent !== undefined ? event.originalEvent.touches : null;\n\n        if (!_.dragging || _.scrolling || touches && touches.length !== 1) {\n            return false;\n        }\n\n        curLeft = _.getLeft(_.currentSlide);\n\n        _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX;\n        _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY;\n\n        _.touchObject.swipeLength = Math.round(Math.sqrt(\n            Math.pow(_.touchObject.curX - _.touchObject.startX, 2)));\n\n        verticalSwipeLength = Math.round(Math.sqrt(\n            Math.pow(_.touchObject.curY - _.touchObject.startY, 2)));\n\n        if (!_.options.verticalSwiping && !_.swiping && verticalSwipeLength > 4) {\n            _.scrolling = true;\n            return false;\n        }\n\n        if (_.options.verticalSwiping === true) {\n            _.touchObject.swipeLength = verticalSwipeLength;\n        }\n\n        swipeDirection = _.swipeDirection();\n\n        if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) {\n            _.swiping = true;\n            event.preventDefault();\n        }\n\n        positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1);\n        if (_.options.verticalSwiping === true) {\n            positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1;\n        }\n\n\n        swipeLength = _.touchObject.swipeLength;\n\n        _.touchObject.edgeHit = false;\n\n        if (_.options.infinite === false) {\n            if ((_.currentSlide === 0 && swipeDirection === 'right') || (_.currentSlide >= _.getDotCount() && swipeDirection === 'left')) {\n                swipeLength = _.touchObject.swipeLength * _.options.edgeFriction;\n                _.touchObject.edgeHit = true;\n            }\n        }\n\n        if (_.options.vertical === false) {\n            _.swipeLeft = curLeft + swipeLength * positionOffset;\n        } else {\n            _.swipeLeft = curLeft + (swipeLength * (_.$list.height() / _.listWidth)) * positionOffset;\n        }\n        if (_.options.verticalSwiping === true) {\n            _.swipeLeft = curLeft + swipeLength * positionOffset;\n        }\n\n        if (_.options.fade === true || _.options.touchMove === false) {\n            return false;\n        }\n\n        if (_.animating === true) {\n            _.swipeLeft = null;\n            return false;\n        }\n\n        _.setCSS(_.swipeLeft);\n\n    };\n\n    Slick.prototype.swipeStart = function(event) {\n\n        var _ = this,\n            touches;\n\n        _.interrupted = true;\n\n        if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) {\n            _.touchObject = {};\n            return false;\n        }\n\n        if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) {\n            touches = event.originalEvent.touches[0];\n        }\n\n        _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX;\n        _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY;\n\n        _.dragging = true;\n\n    };\n\n    Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function() {\n\n        var _ = this;\n\n        if (_.$slidesCache !== null) {\n\n            _.unload();\n\n            _.$slideTrack.children(this.options.slide).detach();\n\n            _.$slidesCache.appendTo(_.$slideTrack);\n\n            _.reinit();\n\n        }\n\n    };\n\n    Slick.prototype.unload = function() {\n\n        var _ = this;\n\n        $('.slick-cloned', _.$slider).remove();\n\n        if (_.$dots) {\n            _.$dots.remove();\n        }\n\n        if (_.$prevArrow && _.htmlExpr.test(_.options.prevArrow)) {\n            _.$prevArrow.remove();\n        }\n\n        if (_.$nextArrow && _.htmlExpr.test(_.options.nextArrow)) {\n            _.$nextArrow.remove();\n        }\n\n        _.$slides\n            .removeClass('slick-slide slick-active slick-visible slick-current')\n            .attr('aria-hidden', 'true')\n            .css('width', '');\n\n    };\n\n    Slick.prototype.unslick = function(fromBreakpoint) {\n\n        var _ = this;\n        _.$slider.trigger('unslick', [_, fromBreakpoint]);\n        _.destroy();\n\n    };\n\n    Slick.prototype.updateArrows = function() {\n\n        var _ = this,\n            centerOffset;\n\n        centerOffset = Math.floor(_.options.slidesToShow / 2);\n\n        if ( _.options.arrows === true &&\n            _.slideCount > _.options.slidesToShow &&\n            !_.options.infinite ) {\n\n            _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');\n            _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');\n\n            if (_.currentSlide === 0) {\n\n                _.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true');\n                _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');\n\n            } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) {\n\n                _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');\n                _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');\n\n            } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) {\n\n                _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');\n                _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');\n\n            }\n\n        }\n\n    };\n\n    Slick.prototype.updateDots = function() {\n\n        var _ = this;\n\n        if (_.$dots !== null) {\n\n            _.$dots\n                .find('li')\n                    .removeClass('slick-active')\n                    .end();\n\n            _.$dots\n                .find('li')\n                .eq(Math.floor(_.currentSlide / _.options.slidesToScroll))\n                .addClass('slick-active');\n\n        }\n\n    };\n\n    Slick.prototype.visibility = function() {\n\n        var _ = this;\n\n        if ( _.options.autoplay ) {\n\n            if ( document[_.hidden] ) {\n\n                _.interrupted = true;\n\n            } else {\n\n                _.interrupted = false;\n\n            }\n\n        }\n\n    };\n\n    $.fn.slick = function() {\n        var _ = this,\n            opt = arguments[0],\n            args = Array.prototype.slice.call(arguments, 1),\n            l = _.length,\n            i,\n            ret;\n        for (i = 0; i < l; i++) {\n            if (typeof opt == 'object' || typeof opt == 'undefined')\n                _[i].slick = new Slick(_[i], opt);\n            else\n                ret = _[i].slick[opt].apply(_[i].slick, args);\n            if (typeof ret != 'undefined') return ret;\n        }\n        return _;\n    };\n\n}));\n","Magento_PageBuilder/js/resource/slick/slick.min.js":"/*\n     _ _      _       _\n ___| (_) ___| | __  (_)___\n/ __| | |/ __| |/ /  | / __|\n\\__ \\ | | (__|   < _ | \\__ \\\n|___/_|_|\\___|_|\\_(_)/ |___/\n                   |__/\n\n Version: 1.9.0\n  Author: Ken Wheeler\n Website: http://kenwheeler.github.io\n    Docs: http://kenwheeler.github.io/slick\n    Repo: http://github.com/kenwheeler/slick\n  Issues: http://github.com/kenwheeler/slick/issues\n\n */\n(function(i){\"use strict\";\"function\"==typeof define&&define.amd?define([\"jquery\"],i):\"undefined\"!=typeof exports?module.exports=i(require(\"jquery\")):i(jQuery)})(function(i){\"use strict\";var e=window.Slick||{};e=function(){function e(e,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(e),appendDots:i(e),arrows:!0,asNavFor:null,prevArrow:'<button class=\"slick-prev\" aria-label=\"Previous\" type=\"button\">Previous</button>',nextArrow:'<button class=\"slick-next\" aria-label=\"Next\" type=\"button\">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:\"50px\",cssEase:\"ease\",customPaging:function(e,t){return i('<button type=\"button\" />').text(t+1)},dots:!1,dotsClass:\"slick-dots\",draggable:!0,easing:\"linear\",edgeFriction:.35,fade:!1,focusOnSelect:!1,focusOnChange:!1,infinite:!0,initialSlide:0,lazyLoad:\"ondemand\",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:\"window\",responsive:null,rows:1,rtl:!1,slide:\"\",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},n.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,scrolling:!1,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,swiping:!1,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},i.extend(n,n.initials),n.activeBreakpoint=null,n.animType=null,n.animProp=null,n.breakpoints=[],n.breakpointSettings=[],n.cssTransitions=!1,n.focussed=!1,n.interrupted=!1,n.hidden=\"hidden\",n.paused=!0,n.positionProp=null,n.respondTo=null,n.rowCount=1,n.shouldClick=!0,n.$slider=i(e),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange=\"visibilitychange\",n.windowWidth=0,n.windowTimer=null,s=i(e).data(\"slick\")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,\"undefined\"!=typeof document.mozHidden?(n.hidden=\"mozHidden\",n.visibilityChange=\"mozvisibilitychange\"):\"undefined\"!=typeof document.webkitHidden&&(n.hidden=\"webkitHidden\",n.visibilityChange=\"webkitvisibilitychange\"),n.autoPlay=i.proxy(n.autoPlay,n),n.autoPlayClear=i.proxy(n.autoPlayClear,n),n.autoPlayIterator=i.proxy(n.autoPlayIterator,n),n.changeSlide=i.proxy(n.changeSlide,n),n.clickHandler=i.proxy(n.clickHandler,n),n.selectHandler=i.proxy(n.selectHandler,n),n.setPosition=i.proxy(n.setPosition,n),n.swipeHandler=i.proxy(n.swipeHandler,n),n.dragHandler=i.proxy(n.dragHandler,n),n.keyHandler=i.proxy(n.keyHandler,n),n.instanceUid=t++,n.htmlExpr=/^(?:\\s*(<[\\w\\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}var t=0;return e}(),e.prototype.activateADA=function(){var i=this;i.$slideTrack.find(\".slick-active\").attr({\"aria-hidden\":\"false\"}).find(\"a, input, button, select\").attr({tabindex:\"0\"})},e.prototype.addSlide=e.prototype.slickAdd=function(e,t,o){var s=this;if(\"boolean\"==typeof t)o=t,t=null;else if(t<0||t>=s.slideCount)return!1;s.unload(),\"number\"==typeof t?0===t&&0===s.$slides.length?i(e).appendTo(s.$slideTrack):o?i(e).insertBefore(s.$slides.eq(t)):i(e).insertAfter(s.$slides.eq(t)):o===!0?i(e).prependTo(s.$slideTrack):i(e).appendTo(s.$slideTrack),s.$slides=s.$slideTrack.children(this.options.slide),s.$slideTrack.children(this.options.slide).detach(),s.$slideTrack.append(s.$slides),s.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e)}),s.$slidesCache=s.$slides,s.reinit()},e.prototype.animateHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.animate({height:e},i.options.speed)}},e.prototype.animateSlide=function(e,t){var o={},s=this;s.animateHeight(),s.options.rtl===!0&&s.options.vertical===!1&&(e=-e),s.transformsEnabled===!1?s.options.vertical===!1?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):s.cssTransitions===!1?(s.options.rtl===!0&&(s.currentLeft=-s.currentLeft),i({animStart:s.currentLeft}).animate({animStart:e},{duration:s.options.speed,easing:s.options.easing,step:function(i){i=Math.ceil(i),s.options.vertical===!1?(o[s.animType]=\"translate(\"+i+\"px, 0px)\",s.$slideTrack.css(o)):(o[s.animType]=\"translate(0px,\"+i+\"px)\",s.$slideTrack.css(o))},complete:function(){t&&t.call()}})):(s.applyTransition(),e=Math.ceil(e),s.options.vertical===!1?o[s.animType]=\"translate3d(\"+e+\"px, 0px, 0px)\":o[s.animType]=\"translate3d(0px,\"+e+\"px, 0px)\",s.$slideTrack.css(o),t&&setTimeout(function(){s.disableTransition(),t.call()},s.options.speed))},e.prototype.getNavTarget=function(){var e=this,t=e.options.asNavFor;return t&&null!==t&&(t=i(t).not(e.$slider)),t},e.prototype.asNavFor=function(e){var t=this,o=t.getNavTarget();null!==o&&\"object\"==typeof o&&o.each(function(){var t=i(this).slick(\"getSlick\");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};e.options.fade===!1?t[e.transitionType]=e.transformType+\" \"+e.options.speed+\"ms \"+e.options.cssEase:t[e.transitionType]=\"opacity \"+e.options.speed+\"ms \"+e.options.cssEase,e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.autoPlay=function(){var i=this;i.autoPlayClear(),i.slideCount>i.options.slidesToShow&&(i.autoPlayTimer=setInterval(i.autoPlayIterator,i.options.autoplaySpeed))},e.prototype.autoPlayClear=function(){var i=this;i.autoPlayTimer&&clearInterval(i.autoPlayTimer)},e.prototype.autoPlayIterator=function(){var i=this,e=i.currentSlide+i.options.slidesToScroll;i.paused||i.interrupted||i.focussed||(i.options.infinite===!1&&(1===i.direction&&i.currentSlide+1===i.slideCount-1?i.direction=0:0===i.direction&&(e=i.currentSlide-i.options.slidesToScroll,i.currentSlide-1===0&&(i.direction=1))),i.slideHandler(e))},e.prototype.buildArrows=function(){var e=this;e.options.arrows===!0&&(e.$prevArrow=i(e.options.prevArrow).addClass(\"slick-arrow\"),e.$nextArrow=i(e.options.nextArrow).addClass(\"slick-arrow\"),e.slideCount>e.options.slidesToShow?(e.$prevArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.$nextArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.prependTo(e.options.appendArrows),e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.appendTo(e.options.appendArrows),e.options.infinite!==!0&&e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\")):e.$prevArrow.add(e.$nextArrow).addClass(\"slick-hidden\").attr({\"aria-disabled\":\"true\",tabindex:\"-1\"}))},e.prototype.buildDots=function(){var e,t,o=this;if(o.options.dots===!0&&o.slideCount>o.options.slidesToShow){for(o.$slider.addClass(\"slick-dotted\"),t=i(\"<ul />\").addClass(o.options.dotsClass),e=0;e<=o.getDotCount();e+=1)t.append(i(\"<li />\").append(o.options.customPaging.call(this,o,e)));o.$dots=t.appendTo(o.options.appendDots),o.$dots.find(\"li\").first().addClass(\"slick-active\")}},e.prototype.buildOut=function(){var e=this;e.$slides=e.$slider.children(e.options.slide+\":not(.slick-cloned)\").addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e).data(\"originalStyling\",i(t).attr(\"style\")||\"\")}),e.$slider.addClass(\"slick-slider\"),e.$slideTrack=0===e.slideCount?i('<div class=\"slick-track\"/>').appendTo(e.$slider):e.$slides.wrapAll('<div class=\"slick-track\"/>').parent(),e.$list=e.$slideTrack.wrap('<div class=\"slick-list\"/>').parent(),e.$slideTrack.css(\"opacity\",0),e.options.centerMode!==!0&&e.options.swipeToSlide!==!0||(e.options.slidesToScroll=1),i(\"img[data-lazy]\",e.$slider).not(\"[src]\").addClass(\"slick-loading\"),e.setupInfinite(),e.buildArrows(),e.buildDots(),e.updateDots(),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.options.draggable===!0&&e.$list.addClass(\"draggable\")},e.prototype.buildRows=function(){var i,e,t,o,s,n,r,l=this;if(o=document.createDocumentFragment(),n=l.$slider.children(),l.options.rows>0){for(r=l.options.slidesPerRow*l.options.rows,s=Math.ceil(n.length/r),i=0;i<s;i++){var d=document.createElement(\"div\");for(e=0;e<l.options.rows;e++){var a=document.createElement(\"div\");for(t=0;t<l.options.slidesPerRow;t++){var c=i*r+(e*l.options.slidesPerRow+t);n.get(c)&&a.appendChild(n.get(c))}d.appendChild(a)}o.appendChild(d)}l.$slider.empty().append(o),l.$slider.children().children().children().css({width:100/l.options.slidesPerRow+\"%\",display:\"inline-block\"})}},e.prototype.checkResponsive=function(e,t){var o,s,n,r=this,l=!1,d=r.$slider.width(),a=window.innerWidth||i(window).width();if(\"window\"===r.respondTo?n=a:\"slider\"===r.respondTo?n=d:\"min\"===r.respondTo&&(n=Math.min(a,d)),r.options.responsive&&r.options.responsive.length&&null!==r.options.responsive){s=null;for(o in r.breakpoints)r.breakpoints.hasOwnProperty(o)&&(r.originalSettings.mobileFirst===!1?n<r.breakpoints[o]&&(s=r.breakpoints[o]):n>r.breakpoints[o]&&(s=r.breakpoints[o]));null!==s?null!==r.activeBreakpoint?(s!==r.activeBreakpoint||t)&&(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||l===!1||r.$slider.trigger(\"breakpoint\",[r,l])}},e.prototype.changeSlide=function(e,t){var o,s,n,r=this,l=i(e.currentTarget);switch(l.is(\"a\")&&e.preventDefault(),l.is(\"li\")||(l=l.closest(\"li\")),n=r.slideCount%r.options.slidesToScroll!==0,o=n?0:(r.slideCount-r.currentSlide)%r.options.slidesToScroll,e.data.message){case\"previous\":s=0===o?r.options.slidesToScroll:r.options.slidesToShow-o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide-s,!1,t);break;case\"next\":s=0===o?r.options.slidesToScroll:o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide+s,!1,t);break;case\"index\":var d=0===e.data.index?0:e.data.index||l.index()*r.options.slidesToScroll;r.slideHandler(r.checkNavigable(d),!1,t),l.children().trigger(\"focus\");break;default:return}},e.prototype.checkNavigable=function(i){var e,t,o=this;if(e=o.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var s in e){if(i<e[s]){i=t;break}t=e[s]}return i},e.prototype.cleanUpEvents=function(){var e=this;e.options.dots&&null!==e.$dots&&(i(\"li\",e.$dots).off(\"click.slick\",e.changeSlide).off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)),e.options.accessibility===!0&&e.$dots.off(\"keydown.slick\",e.keyHandler)),e.$slider.off(\"focus.slick blur.slick\"),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off(\"click.slick\",e.changeSlide),e.$nextArrow&&e.$nextArrow.off(\"click.slick\",e.changeSlide),e.options.accessibility===!0&&(e.$prevArrow&&e.$prevArrow.off(\"keydown.slick\",e.keyHandler),e.$nextArrow&&e.$nextArrow.off(\"keydown.slick\",e.keyHandler))),e.$list.off(\"touchstart.slick mousedown.slick\",e.swipeHandler),e.$list.off(\"touchmove.slick mousemove.slick\",e.swipeHandler),e.$list.off(\"touchend.slick mouseup.slick\",e.swipeHandler),e.$list.off(\"touchcancel.slick mouseleave.slick\",e.swipeHandler),e.$list.off(\"click.slick\",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),e.options.accessibility===!0&&e.$list.off(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().off(\"click.slick\",e.selectHandler),i(window).off(\"orientationchange.slick.slick-\"+e.instanceUid,e.orientationChange),i(window).off(\"resize.slick.slick-\"+e.instanceUid,e.resize),i(\"[draggable!=true]\",e.$slideTrack).off(\"dragstart\",e.preventDefault),i(window).off(\"load.slick.slick-\"+e.instanceUid,e.setPosition)},e.prototype.cleanUpSlideEvents=function(){var e=this;e.$list.off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.cleanUpRows=function(){var i,e=this;e.options.rows>0&&(i=e.$slides.children().children(),i.removeAttr(\"style\"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){var e=this;e.shouldClick===!1&&(i.stopImmediatePropagation(),i.stopPropagation(),i.preventDefault())},e.prototype.destroy=function(e){var t=this;t.autoPlayClear(),t.touchObject={},t.cleanUpEvents(),i(\".slick-cloned\",t.$slider).detach(),t.$dots&&t.$dots.remove(),t.$prevArrow&&t.$prevArrow.length&&(t.$prevArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.prevArrow)&&t.$prevArrow.remove()),t.$nextArrow&&t.$nextArrow.length&&(t.$nextArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.nextArrow)&&t.$nextArrow.remove()),t.$slides&&(t.$slides.removeClass(\"slick-slide slick-active slick-center slick-visible slick-current\").removeAttr(\"aria-hidden\").removeAttr(\"data-slick-index\").each(function(){i(this).attr(\"style\",i(this).data(\"originalStyling\"))}),t.$slideTrack.children(this.options.slide).detach(),t.$slideTrack.detach(),t.$list.detach(),t.$slider.append(t.$slides)),t.cleanUpRows(),t.$slider.removeClass(\"slick-slider\"),t.$slider.removeClass(\"slick-initialized\"),t.$slider.removeClass(\"slick-dotted\"),t.unslicked=!0,e||t.$slider.trigger(\"destroy\",[t])},e.prototype.disableTransition=function(i){var e=this,t={};t[e.transitionType]=\"\",e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;t.cssTransitions===!1?(t.$slides.eq(i).css({zIndex:t.options.zIndex}),t.$slides.eq(i).animate({opacity:1},t.options.speed,t.options.easing,e)):(t.applyTransition(i),t.$slides.eq(i).css({opacity:1,zIndex:t.options.zIndex}),e&&setTimeout(function(){t.disableTransition(i),e.call()},t.options.speed))},e.prototype.fadeSlideOut=function(i){var e=this;e.cssTransitions===!1?e.$slides.eq(i).animate({opacity:0,zIndex:e.options.zIndex-2},e.options.speed,e.options.easing):(e.applyTransition(i),e.$slides.eq(i).css({opacity:0,zIndex:e.options.zIndex-2}))},e.prototype.filterSlides=e.prototype.slickFilter=function(i){var e=this;null!==i&&(e.$slidesCache=e.$slides,e.unload(),e.$slideTrack.children(this.options.slide).detach(),e.$slidesCache.filter(i).appendTo(e.$slideTrack),e.reinit())},e.prototype.focusHandler=function(){var e=this;e.$slider.off(\"focus.slick blur.slick\").on(\"focus.slick\",\"*\",function(t){var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&o.is(\":focus\")&&(e.focussed=!0,e.autoPlay())},0)}).on(\"blur.slick\",\"*\",function(t){i(this);e.options.pauseOnFocus&&(e.focussed=!1,e.autoPlay())})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){var i=this;return i.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(i.options.infinite===!0)if(i.slideCount<=i.options.slidesToShow)++o;else for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else if(i.options.centerMode===!0)o=i.slideCount;else if(i.options.asNavFor)for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else o=1+Math.ceil((i.slideCount-i.options.slidesToShow)/i.options.slidesToScroll);return o-1},e.prototype.getLeft=function(i){var e,t,o,s,n=this,r=0;return n.slideOffset=0,t=n.$slides.first().outerHeight(!0),n.options.infinite===!0?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,n.options.vertical===!0&&n.options.centerMode===!0&&(2===n.options.slidesToShow?s=-1.5:1===n.options.slidesToShow&&(s=-2)),r=t*n.options.slidesToShow*s),n.slideCount%n.options.slidesToScroll!==0&&i+n.options.slidesToScroll>n.slideCount&&n.slideCount>n.options.slidesToShow&&(i>n.slideCount?(n.slideOffset=(n.options.slidesToShow-(i-n.slideCount))*n.slideWidth*-1,r=(n.options.slidesToShow-(i-n.slideCount))*t*-1):(n.slideOffset=n.slideCount%n.options.slidesToScroll*n.slideWidth*-1,r=n.slideCount%n.options.slidesToScroll*t*-1))):i+n.options.slidesToShow>n.slideCount&&(n.slideOffset=(i+n.options.slidesToShow-n.slideCount)*n.slideWidth,r=(i+n.options.slidesToShow-n.slideCount)*t),n.slideCount<=n.options.slidesToShow&&(n.slideOffset=0,r=0),n.options.centerMode===!0&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:n.options.centerMode===!0&&n.options.infinite===!0?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:n.options.centerMode===!0&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=n.options.vertical===!1?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,n.options.variableWidth===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,n.options.centerMode===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow+1),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){var e=this;return e.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(e.options.infinite===!1?i=e.slideCount:(t=e.options.slidesToScroll*-1,o=e.options.slidesToScroll*-1,i=2*e.slideCount);t<i;)s.push(t),t=o+e.options.slidesToScroll,o+=e.options.slidesToScroll<=e.options.slidesToShow?e.options.slidesToScroll:e.options.slidesToShow;return s},e.prototype.getSlick=function(){return this},e.prototype.getSlideCount=function(){var e,t,o,s,n=this;return s=n.options.centerMode===!0?Math.floor(n.$list.width()/2):0,o=n.swipeLeft*-1+s,n.options.swipeToSlide===!0?(n.$slideTrack.find(\".slick-slide\").each(function(e,s){var r,l,d;if(r=i(s).outerWidth(),l=s.offsetLeft,n.options.centerMode!==!0&&(l+=r/2),d=l+r,o<d)return t=s,!1}),e=Math.abs(i(t).attr(\"data-slick-index\")-n.currentSlide)||1):n.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){var t=this;t.changeSlide({data:{message:\"index\",index:parseInt(i)}},e)},e.prototype.init=function(e){var t=this;i(t.$slider).hasClass(\"slick-initialized\")||(i(t.$slider).addClass(\"slick-initialized\"),t.buildRows(),t.buildOut(),t.setProps(),t.startLoad(),t.loadSlider(),t.initializeEvents(),t.updateArrows(),t.updateDots(),t.checkResponsive(!0),t.focusHandler()),e&&t.$slider.trigger(\"init\",[t]),t.options.accessibility===!0&&t.initADA(),t.options.autoplay&&(t.paused=!1,t.autoPlay())},e.prototype.initADA=function(){var e=this,t=Math.ceil(e.slideCount/e.options.slidesToShow),o=e.getNavigableIndexes().filter(function(i){return i>=0&&i<e.slideCount});e.$slides.add(e.$slideTrack.find(\".slick-cloned\")).attr({\"aria-hidden\":\"true\",tabindex:\"-1\"}).find(\"a, input, button, select\").attr({tabindex:\"-1\"}),null!==e.$dots&&(e.$slides.not(e.$slideTrack.find(\".slick-cloned\")).each(function(t){var s=o.indexOf(t);if(i(this).attr({role:\"tabpanel\",id:\"slick-slide\"+e.instanceUid+t,tabindex:-1}),s!==-1){var n=\"slick-slide-control\"+e.instanceUid+s;i(\"#\"+n).length&&i(this).attr({\"aria-describedby\":n})}}),e.$dots.attr(\"role\",\"tablist\").find(\"li\").each(function(s){var n=o[s];i(this).attr({role:\"presentation\"}),i(this).find(\"button\").first().attr({role:\"tab\",id:\"slick-slide-control\"+e.instanceUid+s,\"aria-controls\":\"slick-slide\"+e.instanceUid+n,\"aria-label\":s+1+\" of \"+t,\"aria-selected\":null,tabindex:\"-1\"})}).eq(e.currentSlide).find(\"button\").attr({\"aria-selected\":\"true\",tabindex:\"0\"}).end());for(var s=e.currentSlide,n=s+e.options.slidesToShow;s<n;s++)e.options.focusOnChange?e.$slides.eq(s).attr({tabindex:\"0\"}):e.$slides.eq(s).removeAttr(\"tabindex\");e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.off(\"click.slick\").on(\"click.slick\",{message:\"previous\"},i.changeSlide),i.$nextArrow.off(\"click.slick\").on(\"click.slick\",{message:\"next\"},i.changeSlide),i.options.accessibility===!0&&(i.$prevArrow.on(\"keydown.slick\",i.keyHandler),i.$nextArrow.on(\"keydown.slick\",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;e.options.dots===!0&&e.slideCount>e.options.slidesToShow&&(i(\"li\",e.$dots).on(\"click.slick\",{message:\"index\"},e.changeSlide),e.options.accessibility===!0&&e.$dots.on(\"keydown.slick\",e.keyHandler)),e.options.dots===!0&&e.options.pauseOnDotsHover===!0&&e.slideCount>e.options.slidesToShow&&i(\"li\",e.$dots).on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.initSlideEvents=function(){var e=this;e.options.pauseOnHover&&(e.$list.on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)))},e.prototype.initializeEvents=function(){var e=this;e.initArrowEvents(),e.initDotEvents(),e.initSlideEvents(),e.$list.on(\"touchstart.slick mousedown.slick\",{action:\"start\"},e.swipeHandler),e.$list.on(\"touchmove.slick mousemove.slick\",{action:\"move\"},e.swipeHandler),e.$list.on(\"touchend.slick mouseup.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"touchcancel.slick mouseleave.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"click.slick\",e.clickHandler),i(document).on(e.visibilityChange,i.proxy(e.visibility,e)),e.options.accessibility===!0&&e.$list.on(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),i(window).on(\"orientationchange.slick.slick-\"+e.instanceUid,i.proxy(e.orientationChange,e)),i(window).on(\"resize.slick.slick-\"+e.instanceUid,i.proxy(e.resize,e)),i(\"[draggable!=true]\",e.$slideTrack).on(\"dragstart\",e.preventDefault),i(window).on(\"load.slick.slick-\"+e.instanceUid,e.setPosition),i(e.setPosition)},e.prototype.initUI=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.show()},e.prototype.keyHandler=function(i){var e=this;i.target.tagName.match(\"TEXTAREA|INPUT|SELECT\")||(37===i.keyCode&&e.options.accessibility===!0?e.changeSlide({data:{message:e.options.rtl===!0?\"next\":\"previous\"}}):39===i.keyCode&&e.options.accessibility===!0&&e.changeSlide({data:{message:e.options.rtl===!0?\"previous\":\"next\"}}))},e.prototype.lazyLoad=function(){function e(e){i(\"img[data-lazy]\",e).each(function(){var e=i(this),t=i(this).attr(\"data-lazy\"),o=i(this).attr(\"data-srcset\"),s=i(this).attr(\"data-sizes\")||r.$slider.attr(\"data-sizes\"),n=document.createElement(\"img\");n.onload=function(){e.animate({opacity:0},100,function(){o&&(e.attr(\"srcset\",o),s&&e.attr(\"sizes\",s)),e.attr(\"src\",t).animate({opacity:1},200,function(){e.removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\")}),r.$slider.trigger(\"lazyLoaded\",[r,e,t])})},n.onerror=function(){e.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),r.$slider.trigger(\"lazyLoadError\",[r,e,t])},n.src=t})}var t,o,s,n,r=this;if(r.options.centerMode===!0?r.options.infinite===!0?(s=r.currentSlide+(r.options.slidesToShow/2+1),n=s+r.options.slidesToShow+2):(s=Math.max(0,r.currentSlide-(r.options.slidesToShow/2+1)),n=2+(r.options.slidesToShow/2+1)+r.currentSlide):(s=r.options.infinite?r.options.slidesToShow+r.currentSlide:r.currentSlide,n=Math.ceil(s+r.options.slidesToShow),r.options.fade===!0&&(s>0&&s--,n<=r.slideCount&&n++)),t=r.$slider.find(\".slick-slide\").slice(s,n),\"anticipated\"===r.options.lazyLoad)for(var l=s-1,d=n,a=r.$slider.find(\".slick-slide\"),c=0;c<r.options.slidesToScroll;c++)l<0&&(l=r.slideCount-1),t=t.add(a.eq(l)),t=t.add(a.eq(d)),l--,d++;e(t),r.slideCount<=r.options.slidesToShow?(o=r.$slider.find(\".slick-slide\"),e(o)):r.currentSlide>=r.slideCount-r.options.slidesToShow?(o=r.$slider.find(\".slick-cloned\").slice(0,r.options.slidesToShow),e(o)):0===r.currentSlide&&(o=r.$slider.find(\".slick-cloned\").slice(r.options.slidesToShow*-1),e(o))},e.prototype.loadSlider=function(){var i=this;i.setPosition(),i.$slideTrack.css({opacity:1}),i.$slider.removeClass(\"slick-loading\"),i.initUI(),\"progressive\"===i.options.lazyLoad&&i.progressiveLazyLoad()},e.prototype.next=e.prototype.slickNext=function(){var i=this;i.changeSlide({data:{message:\"next\"}})},e.prototype.orientationChange=function(){var i=this;i.checkResponsive(),i.setPosition()},e.prototype.pause=e.prototype.slickPause=function(){var i=this;i.autoPlayClear(),i.paused=!0},e.prototype.play=e.prototype.slickPlay=function(){var i=this;i.autoPlay(),i.options.autoplay=!0,i.paused=!1,i.focussed=!1,i.interrupted=!1},e.prototype.postSlide=function(e){var t=this;if(!t.unslicked&&(t.$slider.trigger(\"afterChange\",[t,e]),t.animating=!1,t.slideCount>t.options.slidesToShow&&t.setPosition(),t.swipeLeft=null,t.options.autoplay&&t.autoPlay(),t.options.accessibility===!0&&(t.initADA(),t.options.focusOnChange))){var o=i(t.$slides.get(t.currentSlide));o.attr(\"tabindex\",0).focus()}},e.prototype.prev=e.prototype.slickPrev=function(){var i=this;i.changeSlide({data:{message:\"previous\"}})},e.prototype.preventDefault=function(i){i.preventDefault()},e.prototype.progressiveLazyLoad=function(e){e=e||1;var t,o,s,n,r,l=this,d=i(\"img[data-lazy]\",l.$slider);d.length?(t=d.first(),o=t.attr(\"data-lazy\"),s=t.attr(\"data-srcset\"),n=t.attr(\"data-sizes\")||l.$slider.attr(\"data-sizes\"),r=document.createElement(\"img\"),r.onload=function(){s&&(t.attr(\"srcset\",s),n&&t.attr(\"sizes\",n)),t.attr(\"src\",o).removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\"),l.options.adaptiveHeight===!0&&l.setPosition(),l.$slider.trigger(\"lazyLoaded\",[l,t,o]),l.progressiveLazyLoad()},r.onerror=function(){e<3?setTimeout(function(){l.progressiveLazyLoad(e+1)},500):(t.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),l.$slider.trigger(\"lazyLoadError\",[l,t,o]),l.progressiveLazyLoad())},r.src=o):l.$slider.trigger(\"allImagesLoaded\",[l])},e.prototype.refresh=function(e){var t,o,s=this;o=s.slideCount-s.options.slidesToShow,!s.options.infinite&&s.currentSlide>o&&(s.currentSlide=o),s.slideCount<=s.options.slidesToShow&&(s.currentSlide=0),t=s.currentSlide,s.destroy(!0),i.extend(s,s.initials,{currentSlide:t}),s.init(),e||s.changeSlide({data:{message:\"index\",index:t}},!1)},e.prototype.registerBreakpoints=function(){var e,t,o,s=this,n=s.options.responsive||null;if(\"array\"===i.type(n)&&n.length){s.respondTo=s.options.respondTo||\"window\";for(e in n)if(o=s.breakpoints.length-1,n.hasOwnProperty(e)){for(t=n[e].breakpoint;o>=0;)s.breakpoints[o]&&s.breakpoints[o]===t&&s.breakpoints.splice(o,1),o--;s.breakpoints.push(t),s.breakpointSettings[t]=n[e].settings}s.breakpoints.sort(function(i,e){return s.options.mobileFirst?i-e:e-i})}},e.prototype.reinit=function(){var e=this;e.$slides=e.$slideTrack.children(e.options.slide).addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.currentSlide>=e.slideCount&&0!==e.currentSlide&&(e.currentSlide=e.currentSlide-e.options.slidesToScroll),e.slideCount<=e.options.slidesToShow&&(e.currentSlide=0),e.registerBreakpoints(),e.setProps(),e.setupInfinite(),e.buildArrows(),e.updateArrows(),e.initArrowEvents(),e.buildDots(),e.updateDots(),e.initDotEvents(),e.cleanUpSlideEvents(),e.initSlideEvents(),e.checkResponsive(!1,!0),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.setPosition(),e.focusHandler(),e.paused=!e.options.autoplay,e.autoPlay(),e.$slider.trigger(\"reInit\",[e])},e.prototype.resize=function(){var e=this;i(window).width()!==e.windowWidth&&(clearTimeout(e.windowDelay),e.windowDelay=window.setTimeout(function(){e.windowWidth=i(window).width(),e.checkResponsive(),e.unslicked||e.setPosition()},50))},e.prototype.removeSlide=e.prototype.slickRemove=function(i,e,t){var o=this;return\"boolean\"==typeof i?(e=i,i=e===!0?0:o.slideCount-1):i=e===!0?--i:i,!(o.slideCount<1||i<0||i>o.slideCount-1)&&(o.unload(),t===!0?o.$slideTrack.children().remove():o.$slideTrack.children(this.options.slide).eq(i).remove(),o.$slides=o.$slideTrack.children(this.options.slide),o.$slideTrack.children(this.options.slide).detach(),o.$slideTrack.append(o.$slides),o.$slidesCache=o.$slides,void o.reinit())},e.prototype.setCSS=function(i){var e,t,o=this,s={};o.options.rtl===!0&&(i=-i),e=\"left\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",t=\"top\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",s[o.positionProp]=i,o.transformsEnabled===!1?o.$slideTrack.css(s):(s={},o.cssTransitions===!1?(s[o.animType]=\"translate(\"+e+\", \"+t+\")\",o.$slideTrack.css(s)):(s[o.animType]=\"translate3d(\"+e+\", \"+t+\", 0px)\",o.$slideTrack.css(s)))},e.prototype.setDimensions=function(){var i=this;i.options.vertical===!1?i.options.centerMode===!0&&i.$list.css({padding:\"0px \"+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),i.options.centerMode===!0&&i.$list.css({padding:i.options.centerPadding+\" 0px\"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),i.options.vertical===!1&&i.options.variableWidth===!1?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(\".slick-slide\").length))):i.options.variableWidth===!0?i.$slideTrack.width(5e3*i.slideCount):(i.slideWidth=Math.ceil(i.listWidth),i.$slideTrack.height(Math.ceil(i.$slides.first().outerHeight(!0)*i.$slideTrack.children(\".slick-slide\").length)));var e=i.$slides.first().outerWidth(!0)-i.$slides.first().width();i.options.variableWidth===!1&&i.$slideTrack.children(\".slick-slide\").width(i.slideWidth-e)},e.prototype.setFade=function(){var e,t=this;t.$slides.each(function(o,s){e=t.slideWidth*o*-1,t.options.rtl===!0?i(s).css({position:\"relative\",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}):i(s).css({position:\"relative\",left:e,top:0,zIndex:t.options.zIndex-2,opacity:0})}),t.$slides.eq(t.currentSlide).css({zIndex:t.options.zIndex-1,opacity:1})},e.prototype.setHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.css(\"height\",e)}},e.prototype.setOption=e.prototype.slickSetOption=function(){var e,t,o,s,n,r=this,l=!1;if(\"object\"===i.type(arguments[0])?(o=arguments[0],l=arguments[1],n=\"multiple\"):\"string\"===i.type(arguments[0])&&(o=arguments[0],s=arguments[1],l=arguments[2],\"responsive\"===arguments[0]&&\"array\"===i.type(arguments[1])?n=\"responsive\":\"undefined\"!=typeof arguments[1]&&(n=\"single\")),\"single\"===n)r.options[o]=s;else if(\"multiple\"===n)i.each(o,function(i,e){r.options[i]=e});else if(\"responsive\"===n)for(t in s)if(\"array\"!==i.type(r.options.responsive))r.options.responsive=[s[t]];else{for(e=r.options.responsive.length-1;e>=0;)r.options.responsive[e].breakpoint===s[t].breakpoint&&r.options.responsive.splice(e,1),e--;r.options.responsive.push(s[t])}l&&(r.unload(),r.reinit())},e.prototype.setPosition=function(){var i=this;i.setDimensions(),i.setHeight(),i.options.fade===!1?i.setCSS(i.getLeft(i.currentSlide)):i.setFade(),i.$slider.trigger(\"setPosition\",[i])},e.prototype.setProps=function(){var i=this,e=document.body.style;i.positionProp=i.options.vertical===!0?\"top\":\"left\",\n\"top\"===i.positionProp?i.$slider.addClass(\"slick-vertical\"):i.$slider.removeClass(\"slick-vertical\"),void 0===e.WebkitTransition&&void 0===e.MozTransition&&void 0===e.msTransition||i.options.useCSS===!0&&(i.cssTransitions=!0),i.options.fade&&(\"number\"==typeof i.options.zIndex?i.options.zIndex<3&&(i.options.zIndex=3):i.options.zIndex=i.defaults.zIndex),void 0!==e.OTransform&&(i.animType=\"OTransform\",i.transformType=\"-o-transform\",i.transitionType=\"OTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.MozTransform&&(i.animType=\"MozTransform\",i.transformType=\"-moz-transform\",i.transitionType=\"MozTransition\",void 0===e.perspectiveProperty&&void 0===e.MozPerspective&&(i.animType=!1)),void 0!==e.webkitTransform&&(i.animType=\"webkitTransform\",i.transformType=\"-webkit-transform\",i.transitionType=\"webkitTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.msTransform&&(i.animType=\"msTransform\",i.transformType=\"-ms-transform\",i.transitionType=\"msTransition\",void 0===e.msTransform&&(i.animType=!1)),void 0!==e.transform&&i.animType!==!1&&(i.animType=\"transform\",i.transformType=\"transform\",i.transitionType=\"transition\"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&i.animType!==!1},e.prototype.setSlideClasses=function(i){var e,t,o,s,n=this;if(t=n.$slider.find(\".slick-slide\").removeClass(\"slick-active slick-center slick-current\").attr(\"aria-hidden\",\"true\"),n.$slides.eq(i).addClass(\"slick-current\"),n.options.centerMode===!0){var r=n.options.slidesToShow%2===0?1:0;e=Math.floor(n.options.slidesToShow/2),n.options.infinite===!0&&(i>=e&&i<=n.slideCount-1-e?n.$slides.slice(i-e+r,i+e+1).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(o=n.options.slidesToShow+i,t.slice(o-e+1+r,o+e+2).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\")),0===i?t.eq(t.length-1-n.options.slidesToShow).addClass(\"slick-center\"):i===n.slideCount-1&&t.eq(n.options.slidesToShow).addClass(\"slick-center\")),n.$slides.eq(i).addClass(\"slick-center\")}else i>=0&&i<=n.slideCount-n.options.slidesToShow?n.$slides.slice(i,i+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.length<=n.options.slidesToShow?t.addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(s=n.slideCount%n.options.slidesToShow,o=n.options.infinite===!0?n.options.slidesToShow+i:i,n.options.slidesToShow==n.options.slidesToScroll&&n.slideCount-i<n.options.slidesToShow?t.slice(o-(n.options.slidesToShow-s),o+s).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.slice(o,o+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"));\"ondemand\"!==n.options.lazyLoad&&\"anticipated\"!==n.options.lazyLoad||n.lazyLoad()},e.prototype.setupInfinite=function(){var e,t,o,s=this;if(s.options.fade===!0&&(s.options.centerMode=!1),s.options.infinite===!0&&s.options.fade===!1&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=s.options.centerMode===!0?s.options.slidesToShow+1:s.options.slidesToShow,e=s.slideCount;e>s.slideCount-o;e-=1)t=e-1,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t-s.slideCount).prependTo(s.$slideTrack).addClass(\"slick-cloned\");for(e=0;e<o+s.slideCount;e+=1)t=e,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t+s.slideCount).appendTo(s.$slideTrack).addClass(\"slick-cloned\");s.$slideTrack.find(\".slick-cloned\").find(\"[id]\").each(function(){i(this).attr(\"id\",\"\")})}},e.prototype.interrupt=function(i){var e=this;i||e.autoPlay(),e.interrupted=i},e.prototype.selectHandler=function(e){var t=this,o=i(e.target).is(\".slick-slide\")?i(e.target):i(e.target).parents(\".slick-slide\"),s=parseInt(o.attr(\"data-slick-index\"));return s||(s=0),t.slideCount<=t.options.slidesToShow?void t.slideHandler(s,!1,!0):void t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(a.animating===!0&&a.options.waitForAnimate===!0||a.options.fade===!0&&a.currentSlide===i))return e===!1&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,a.options.infinite===!1&&a.options.centerMode===!1&&(i<0||i>a.getDotCount()*a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):a.options.infinite===!1&&a.options.centerMode===!0&&(i<0||i>a.slideCount-a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!==0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+o:o>=a.slideCount?a.slideCount%a.options.slidesToScroll!==0?0:o-a.slideCount:o,a.animating=!0,a.$slider.trigger(\"beforeChange\",[a,a.currentSlide,s]),n=a.currentSlide,a.currentSlide=s,a.setSlideClasses(a.currentSlide),a.options.asNavFor&&(l=a.getNavTarget(),l=l.slick(\"getSlick\"),l.slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide)),a.updateDots(),a.updateArrows(),a.options.fade===!0?(t!==!0?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight()):void(t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)))},e.prototype.startLoad=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.hide(),i.$slider.addClass(\"slick-loading\")},e.prototype.swipeDirection=function(){var i,e,t,o,s=this;return i=s.touchObject.startX-s.touchObject.curX,e=s.touchObject.startY-s.touchObject.curY,t=Math.atan2(e,i),o=Math.round(180*t/Math.PI),o<0&&(o=360-Math.abs(o)),o<=45&&o>=0?s.options.rtl===!1?\"left\":\"right\":o<=360&&o>=315?s.options.rtl===!1?\"left\":\"right\":o>=135&&o<=225?s.options.rtl===!1?\"right\":\"left\":s.options.verticalSwiping===!0?o>=35&&o<=135?\"down\":\"up\":\"vertical\"},e.prototype.swipeEnd=function(i){var e,t,o=this;if(o.dragging=!1,o.swiping=!1,o.scrolling)return o.scrolling=!1,!1;if(o.interrupted=!1,o.shouldClick=!(o.touchObject.swipeLength>10),void 0===o.touchObject.curX)return!1;if(o.touchObject.edgeHit===!0&&o.$slider.trigger(\"edge\",[o,o.swipeDirection()]),o.touchObject.swipeLength>=o.touchObject.minSwipe){switch(t=o.swipeDirection()){case\"left\":case\"down\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide+o.getSlideCount()):o.currentSlide+o.getSlideCount(),o.currentDirection=0;break;case\"right\":case\"up\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide-o.getSlideCount()):o.currentSlide-o.getSlideCount(),o.currentDirection=1}\"vertical\"!=t&&(o.slideHandler(e),o.touchObject={},o.$slider.trigger(\"swipe\",[o,t]))}else o.touchObject.startX!==o.touchObject.curX&&(o.slideHandler(o.currentSlide),o.touchObject={})},e.prototype.swipeHandler=function(i){var e=this;if(!(e.options.swipe===!1||\"ontouchend\"in document&&e.options.swipe===!1||e.options.draggable===!1&&i.type.indexOf(\"mouse\")!==-1))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,e.options.verticalSwiping===!0&&(e.touchObject.minSwipe=e.listHeight/e.options.touchThreshold),i.data.action){case\"start\":e.swipeStart(i);break;case\"move\":e.swipeMove(i);break;case\"end\":e.swipeEnd(i)}},e.prototype.swipeMove=function(i){var e,t,o,s,n,r,l=this;return n=void 0!==i.originalEvent?i.originalEvent.touches:null,!(!l.dragging||l.scrolling||n&&1!==n.length)&&(e=l.getLeft(l.currentSlide),l.touchObject.curX=void 0!==n?n[0].pageX:i.clientX,l.touchObject.curY=void 0!==n?n[0].pageY:i.clientY,l.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(l.touchObject.curX-l.touchObject.startX,2))),r=Math.round(Math.sqrt(Math.pow(l.touchObject.curY-l.touchObject.startY,2))),!l.options.verticalSwiping&&!l.swiping&&r>4?(l.scrolling=!0,!1):(l.options.verticalSwiping===!0&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(l.options.rtl===!1?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),l.options.verticalSwiping===!0&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,l.options.infinite===!1&&(0===l.currentSlide&&\"right\"===t||l.currentSlide>=l.getDotCount()&&\"left\"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),l.options.vertical===!1?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,l.options.verticalSwiping===!0&&(l.swipeLeft=e+o*s),l.options.fade!==!0&&l.options.touchMove!==!1&&(l.animating===!0?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;return t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow?(t.touchObject={},!1):(void 0!==i.originalEvent&&void 0!==i.originalEvent.touches&&(e=i.originalEvent.touches[0]),t.touchObject.startX=t.touchObject.curX=void 0!==e?e.pageX:i.clientX,t.touchObject.startY=t.touchObject.curY=void 0!==e?e.pageY:i.clientY,void(t.dragging=!0))},e.prototype.unfilterSlides=e.prototype.slickUnfilter=function(){var i=this;null!==i.$slidesCache&&(i.unload(),i.$slideTrack.children(this.options.slide).detach(),i.$slidesCache.appendTo(i.$slideTrack),i.reinit())},e.prototype.unload=function(){var e=this;i(\".slick-cloned\",e.$slider).remove(),e.$dots&&e.$dots.remove(),e.$prevArrow&&e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.remove(),e.$nextArrow&&e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.remove(),e.$slides.removeClass(\"slick-slide slick-active slick-visible slick-current\").attr(\"aria-hidden\",\"true\").css(\"width\",\"\")},e.prototype.unslick=function(i){var e=this;e.$slider.trigger(\"unslick\",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i,e=this;i=Math.floor(e.options.slidesToShow/2),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&!e.options.infinite&&(e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),0===e.currentSlide?(e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-e.options.slidesToShow&&e.options.centerMode===!1?(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-1&&e.options.centerMode===!0&&(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")))},e.prototype.updateDots=function(){var i=this;null!==i.$dots&&(i.$dots.find(\"li\").removeClass(\"slick-active\").end(),i.$dots.find(\"li\").eq(Math.floor(i.currentSlide/i.options.slidesToScroll)).addClass(\"slick-active\"))},e.prototype.visibility=function(){var i=this;i.options.autoplay&&(document[i.hidden]?i.interrupted=!0:i.interrupted=!1)},i.fn.slick=function(){var i,t,o=this,s=arguments[0],n=Array.prototype.slice.call(arguments,1),r=o.length;for(i=0;i<r;i++)if(\"object\"==typeof s||\"undefined\"==typeof s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),\"undefined\"!=typeof t)return t;return o}});\n","Magento_PageBuilder/js/resource/jarallax/jarallax-video.js":"/*!\n * Video Extension for Jarallax v2.0.3 (https://github.com/nk-o/jarallax)\n * Copyright 2022 nK <https://nkdev.info>\n * Licensed under MIT (https://github.com/nk-o/jarallax/blob/master/LICENSE)\n */\n\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n      typeof define === 'function' && define.amd ? define(factory) :\n          (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.jarallaxVideo = factory());\n})(this, (function () { 'use strict';\n\n  /*!\n   * Name    : Video Worker\n   * Version : 2.0.0\n   * Author  : nK <https://nkdev.info>\n   * GitHub  : https://github.com/nk-o/video-worker\n   */\n\n  /* eslint-disable import/no-mutable-exports */\n\n  /* eslint-disable no-restricted-globals */\n  let win$1;\n\n  if (typeof window !== 'undefined') {\n    win$1 = window;\n  } else if (typeof global !== 'undefined') {\n    win$1 = global;\n  } else if (typeof self !== 'undefined') {\n    win$1 = self;\n  } else {\n    win$1 = {};\n  }\n\n  var global$1$1 = win$1; // Deferred\n  // thanks http://stackoverflow.com/questions/18096715/implement-deferred-object-without-using-jquery\n\n  function Deferred() {\n    this.doneCallbacks = [];\n    this.failCallbacks = [];\n  }\n\n  Deferred.prototype = {\n    execute(list, args) {\n      let i = list.length; // eslint-disable-next-line no-param-reassign\n\n      args = Array.prototype.slice.call(args);\n\n      while (i) {\n        i -= 1;\n        list[i].apply(null, args);\n      }\n    },\n\n    resolve(...args) {\n      this.execute(this.doneCallbacks, args);\n    },\n\n    reject(...args) {\n      this.execute(this.failCallbacks, args);\n    },\n\n    done(callback) {\n      this.doneCallbacks.push(callback);\n    },\n\n    fail(callback) {\n      this.failCallbacks.push(callback);\n    }\n\n  };\n  let ID = 0;\n  let YoutubeAPIadded = 0;\n  let VimeoAPIadded = 0;\n  let loadingYoutubePlayer = 0;\n  let loadingVimeoPlayer = 0;\n  const loadingYoutubeDefer = /*#__PURE__*/new Deferred();\n  const loadingVimeoDefer = /*#__PURE__*/new Deferred();\n\n  class VideoWorker {\n    constructor(url, options) {\n      const self = this;\n      self.url = url;\n      self.options_default = {\n        autoplay: false,\n        loop: false,\n        mute: false,\n        volume: 100,\n        showControls: true,\n        accessibilityHidden: false,\n        // start / end video time in seconds\n        startTime: 0,\n        endTime: 0\n      };\n      self.options = self.extend({}, self.options_default, options); // Fix wrong option name.\n      // Thanks to https://github.com/nk-o/video-worker/issues/13.\n\n      if (typeof self.options.showContols !== 'undefined') {\n        self.options.showControls = self.options.showContols;\n        delete self.options.showContols;\n      } // check URL\n\n\n      self.videoID = self.parseURL(url); // init\n\n      if (self.videoID) {\n        self.ID = ID;\n        ID += 1;\n        self.loadAPI();\n        self.init();\n      }\n    } // Extend like jQuery.extend\n    // eslint-disable-next-line class-methods-use-this\n\n\n    extend(...args) {\n      const out = args[0] || {};\n      Object.keys(args).forEach(i => {\n        if (!args[i]) {\n          return;\n        }\n\n        Object.keys(args[i]).forEach(key => {\n          out[key] = args[i][key];\n        });\n      });\n      return out;\n    }\n\n    parseURL(url) {\n      // parse youtube ID\n      function getYoutubeID(ytUrl) {\n        // eslint-disable-next-line no-useless-escape\n        const regExp = /.*(?:youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=)([^#\\&\\?]*).*/;\n        const match = ytUrl.match(regExp);\n        return match && match[1].length === 11 ? match[1] : false;\n      } // parse vimeo ID\n\n\n      function getVimeoID(vmUrl) {\n        // eslint-disable-next-line no-useless-escape\n        const regExp = /https?:\\/\\/(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/([^/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|video\\/|)(\\d+)(?:$|\\/|\\?)/;\n        const match = vmUrl.match(regExp);\n        return match && match[3] ? match[3] : false;\n      } // parse local string\n\n\n      function getLocalVideos(locUrl) {\n        // eslint-disable-next-line no-useless-escape\n        const videoFormats = locUrl.split(/,(?=mp4\\:|webm\\:|ogv\\:|ogg\\:)/);\n        const result = {};\n        let ready = 0;\n        videoFormats.forEach(val => {\n          // eslint-disable-next-line no-useless-escape\n          const match = val.match(/^(mp4|webm|ogv|ogg)\\:(.*)/);\n\n          if (match && match[1] && match[2]) {\n            // eslint-disable-next-line prefer-destructuring\n            result[match[1] === 'ogv' ? 'ogg' : match[1]] = match[2];\n            ready = 1;\n          }\n        });\n        return ready ? result : false;\n      }\n\n      const Youtube = getYoutubeID(url);\n      const Vimeo = getVimeoID(url);\n      const Local = getLocalVideos(url);\n\n      if (Youtube) {\n        this.type = 'youtube';\n        return Youtube;\n      }\n\n      if (Vimeo) {\n        this.type = 'vimeo';\n        return Vimeo;\n      }\n\n      if (Local) {\n        this.type = 'local';\n        return Local;\n      }\n\n      return false;\n    }\n\n    isValid() {\n      return !!this.videoID;\n    } // events\n\n\n    on(name, callback) {\n      this.userEventsList = this.userEventsList || []; // add new callback in events list\n\n      (this.userEventsList[name] || (this.userEventsList[name] = [])).push(callback);\n    }\n\n    off(name, callback) {\n      if (!this.userEventsList || !this.userEventsList[name]) {\n        return;\n      }\n\n      if (!callback) {\n        delete this.userEventsList[name];\n      } else {\n        this.userEventsList[name].forEach((val, key) => {\n          if (val === callback) {\n            this.userEventsList[name][key] = false;\n          }\n        });\n      }\n    }\n\n    fire(name, ...args) {\n      if (this.userEventsList && typeof this.userEventsList[name] !== 'undefined') {\n        this.userEventsList[name].forEach(val => {\n          // call with all arguments\n          if (val) {\n            val.apply(this, args);\n          }\n        });\n      }\n    }\n\n    play(start) {\n      const self = this;\n\n      if (!self.player) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.playVideo) {\n        if (typeof start !== 'undefined') {\n          self.player.seekTo(start || 0);\n        }\n\n        if (global$1$1.YT.PlayerState.PLAYING !== self.player.getPlayerState()) {\n          self.player.playVideo();\n        }\n      }\n\n      if (self.type === 'vimeo') {\n        if (typeof start !== 'undefined') {\n          self.player.setCurrentTime(start);\n        }\n\n        self.player.getPaused().then(paused => {\n          if (paused) {\n            self.player.play();\n          }\n        });\n      }\n\n      if (self.type === 'local') {\n        if (typeof start !== 'undefined') {\n          self.player.currentTime = start;\n        }\n\n        if (self.player.paused) {\n          self.player.play();\n        }\n      }\n    }\n\n    pause() {\n      const self = this;\n\n      if (!self.player) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.pauseVideo) {\n        if (global$1$1.YT.PlayerState.PLAYING === self.player.getPlayerState()) {\n          self.player.pauseVideo();\n        }\n      }\n\n      if (self.type === 'vimeo') {\n        self.player.getPaused().then(paused => {\n          if (!paused) {\n            self.player.pause();\n          }\n        });\n      }\n\n      if (self.type === 'local') {\n        if (!self.player.paused) {\n          self.player.pause();\n        }\n      }\n    }\n\n    mute() {\n      const self = this;\n\n      if (!self.player) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.mute) {\n        self.player.mute();\n      }\n\n      if (self.type === 'vimeo' && self.player.setVolume) {\n        self.player.setVolume(0);\n      }\n\n      if (self.type === 'local') {\n        self.$video.muted = true;\n      }\n    }\n\n    unmute() {\n      const self = this;\n\n      if (!self.player) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.mute) {\n        self.player.unMute();\n      }\n\n      if (self.type === 'vimeo' && self.player.setVolume) {\n        self.player.setVolume(self.options.volume);\n      }\n\n      if (self.type === 'local') {\n        self.$video.muted = false;\n      }\n    }\n\n    setVolume(volume = false) {\n      const self = this;\n\n      if (!self.player || !volume) {\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.setVolume) {\n        self.player.setVolume(volume);\n      }\n\n      if (self.type === 'vimeo' && self.player.setVolume) {\n        self.player.setVolume(volume);\n      }\n\n      if (self.type === 'local') {\n        self.$video.volume = volume / 100;\n      }\n    }\n\n    getVolume(callback) {\n      const self = this;\n\n      if (!self.player) {\n        callback(false);\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.getVolume) {\n        callback(self.player.getVolume());\n      }\n\n      if (self.type === 'vimeo' && self.player.getVolume) {\n        self.player.getVolume().then(volume => {\n          callback(volume);\n        });\n      }\n\n      if (self.type === 'local') {\n        callback(self.$video.volume * 100);\n      }\n    }\n\n    getMuted(callback) {\n      const self = this;\n\n      if (!self.player) {\n        callback(null);\n        return;\n      }\n\n      if (self.type === 'youtube' && self.player.isMuted) {\n        callback(self.player.isMuted());\n      }\n\n      if (self.type === 'vimeo' && self.player.getVolume) {\n        self.player.getVolume().then(volume => {\n          callback(!!volume);\n        });\n      }\n\n      if (self.type === 'local') {\n        callback(self.$video.muted);\n      }\n    }\n\n    getImageURL(callback) {\n      const self = this;\n\n      if (self.videoImage) {\n        callback(self.videoImage);\n        return;\n      }\n\n      if (self.type === 'youtube') {\n        const availableSizes = ['maxresdefault', 'sddefault', 'hqdefault', '0'];\n        let step = 0;\n        const tempImg = new Image();\n\n        tempImg.onload = function () {\n          // if no thumbnail, youtube add their own image with width = 120px\n          if ((this.naturalWidth || this.width) !== 120 || step === availableSizes.length - 1) {\n            // ok\n            self.videoImage = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n            callback(self.videoImage);\n          } else {\n            // try another size\n            step += 1;\n            this.src = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n          }\n        };\n\n        tempImg.src = `https://img.youtube.com/vi/${self.videoID}/${availableSizes[step]}.jpg`;\n      }\n\n      if (self.type === 'vimeo') {\n        let request = new XMLHttpRequest(); // https://vimeo.com/api/oembed.json?url=https://vimeo.com/235212527\n\n        request.open('GET', `https://vimeo.com/api/oembed.json?url=${self.url}`, true);\n\n        request.onreadystatechange = function () {\n          if (this.readyState === 4) {\n            if (this.status >= 200 && this.status < 400) {\n              // Success!\n              const response = JSON.parse(this.responseText);\n\n              if (response.thumbnail_url) {\n                self.videoImage = response.thumbnail_url;\n                callback(self.videoImage);\n              }\n            }\n          }\n        };\n\n        request.send();\n        request = null;\n      }\n    } // fallback to the old version.\n\n\n    getIframe(callback) {\n      this.getVideo(callback);\n    }\n\n    getVideo(callback) {\n      const self = this; // return generated video block\n\n      if (self.$video) {\n        callback(self.$video);\n        return;\n      } // generate new video block\n\n\n      self.onAPIready(() => {\n        let hiddenDiv;\n\n        if (!self.$video) {\n          hiddenDiv = document.createElement('div');\n          hiddenDiv.style.display = 'none';\n        } // Youtube\n\n\n        if (self.type === 'youtube') {\n          self.playerOptions = {\n            // GDPR Compliance.\n            host: 'https://www.youtube-nocookie.com',\n            videoId: self.videoID,\n            playerVars: {\n              autohide: 1,\n              rel: 0,\n              autoplay: 0,\n              // autoplay enable on mobile devices\n              playsinline: 1\n            }\n          }; // hide controls\n\n          if (!self.options.showControls) {\n            self.playerOptions.playerVars.iv_load_policy = 3;\n            self.playerOptions.playerVars.modestbranding = 1;\n            self.playerOptions.playerVars.controls = 0;\n            self.playerOptions.playerVars.showinfo = 0;\n            self.playerOptions.playerVars.disablekb = 1;\n          } // events\n\n\n          let ytStarted;\n          let ytProgressInterval;\n          self.playerOptions.events = {\n            onReady(e) {\n              // mute\n              if (self.options.mute) {\n                e.target.mute();\n              } else if (self.options.volume) {\n                e.target.setVolume(self.options.volume);\n              } // autoplay\n\n\n              if (self.options.autoplay) {\n                self.play(self.options.startTime);\n              }\n\n              self.fire('ready', e); // For seamless loops, set the endTime to 0.1 seconds less than the video's duration\n              // https://github.com/nk-o/video-worker/issues/2\n\n              if (self.options.loop && !self.options.endTime) {\n                const secondsOffset = 0.1;\n                self.options.endTime = self.player.getDuration() - secondsOffset;\n              } // volumechange\n\n\n              setInterval(() => {\n                self.getVolume(volume => {\n                  if (self.options.volume !== volume) {\n                    self.options.volume = volume;\n                    self.fire('volumechange', e);\n                  }\n                });\n              }, 150);\n            },\n\n            onStateChange(e) {\n              // loop\n              if (self.options.loop && e.data === global$1$1.YT.PlayerState.ENDED) {\n                self.play(self.options.startTime);\n              }\n\n              if (!ytStarted && e.data === global$1$1.YT.PlayerState.PLAYING) {\n                ytStarted = 1;\n                self.fire('started', e);\n              }\n\n              if (e.data === global$1$1.YT.PlayerState.PLAYING) {\n                self.fire('play', e);\n              }\n\n              if (e.data === global$1$1.YT.PlayerState.PAUSED) {\n                self.fire('pause', e);\n              }\n\n              if (e.data === global$1$1.YT.PlayerState.ENDED) {\n                self.fire('ended', e);\n              } // progress check\n\n\n              if (e.data === global$1$1.YT.PlayerState.PLAYING) {\n                ytProgressInterval = setInterval(() => {\n                  self.fire('timeupdate', e); // check for end of video and play again or stop\n\n                  if (self.options.endTime && self.player.getCurrentTime() >= self.options.endTime) {\n                    if (self.options.loop) {\n                      self.play(self.options.startTime);\n                    } else {\n                      self.pause();\n                    }\n                  }\n                }, 150);\n              } else {\n                clearInterval(ytProgressInterval);\n              }\n            },\n\n            onError(e) {\n              self.fire('error', e);\n            }\n\n          };\n          const firstInit = !self.$video;\n\n          if (firstInit) {\n            const div = document.createElement('div');\n            div.setAttribute('id', self.playerID);\n            hiddenDiv.appendChild(div);\n            document.body.appendChild(hiddenDiv);\n          }\n\n          self.player = self.player || new global$1$1.YT.Player(self.playerID, self.playerOptions);\n\n          if (firstInit) {\n            self.$video = document.getElementById(self.playerID); // add accessibility attributes\n\n            if (self.options.accessibilityHidden) {\n              self.$video.setAttribute('tabindex', '-1');\n              self.$video.setAttribute('aria-hidden', 'true');\n            } // get video width and height\n\n\n            self.videoWidth = parseInt(self.$video.getAttribute('width'), 10) || 1280;\n            self.videoHeight = parseInt(self.$video.getAttribute('height'), 10) || 720;\n          }\n        } // Vimeo\n\n\n        if (self.type === 'vimeo') {\n          self.playerOptions = {\n            // GDPR Compliance.\n            dnt: 1,\n            id: self.videoID,\n            autopause: 0,\n            transparent: 0,\n            autoplay: self.options.autoplay ? 1 : 0,\n            loop: self.options.loop ? 1 : 0,\n            muted: self.options.mute ? 1 : 0\n          };\n\n          if (self.options.volume) {\n            self.playerOptions.volume = self.options.volume;\n          } // hide controls\n\n\n          if (!self.options.showControls) {\n            self.playerOptions.badge = 0;\n            self.playerOptions.byline = 0;\n            self.playerOptions.portrait = 0;\n            self.playerOptions.title = 0;\n            self.playerOptions.background = 1;\n          }\n\n          if (!self.$video) {\n            let playerOptionsString = '';\n            Object.keys(self.playerOptions).forEach(key => {\n              if (playerOptionsString !== '') {\n                playerOptionsString += '&';\n              }\n\n              playerOptionsString += `${key}=${encodeURIComponent(self.playerOptions[key])}`;\n            }); // we need to create iframe manually because when we create it using API\n            // js events won't triggers after iframe moved to another place\n\n            self.$video = document.createElement('iframe');\n            self.$video.setAttribute('id', self.playerID);\n            self.$video.setAttribute('src', `https://player.vimeo.com/video/${self.videoID}?${playerOptionsString}`);\n            self.$video.setAttribute('frameborder', '0');\n            self.$video.setAttribute('mozallowfullscreen', '');\n            self.$video.setAttribute('allowfullscreen', '');\n            self.$video.setAttribute('title', 'Vimeo video player'); // add accessibility attributes\n\n            if (self.options.accessibilityHidden) {\n              self.$video.setAttribute('tabindex', '-1');\n              self.$video.setAttribute('aria-hidden', 'true');\n            }\n\n            hiddenDiv.appendChild(self.$video);\n            document.body.appendChild(hiddenDiv);\n          }\n\n          self.player = self.player || new global$1$1.Vimeo.Player(self.$video, self.playerOptions); // set current time for autoplay\n\n          if (self.options.startTime && self.options.autoplay) {\n            self.player.setCurrentTime(self.options.startTime);\n          } // get video width and height\n\n\n          self.player.getVideoWidth().then(width => {\n            self.videoWidth = width || 1280;\n          });\n          self.player.getVideoHeight().then(height => {\n            self.videoHeight = height || 720;\n          }); // events\n\n          let vmStarted;\n          self.player.on('timeupdate', e => {\n            if (!vmStarted) {\n              self.fire('started', e);\n              vmStarted = 1;\n            }\n\n            self.fire('timeupdate', e); // check for end of video and play again or stop\n\n            if (self.options.endTime) {\n              if (self.options.endTime && e.seconds >= self.options.endTime) {\n                if (self.options.loop) {\n                  self.play(self.options.startTime);\n                } else {\n                  self.pause();\n                }\n              }\n            }\n          });\n          self.player.on('play', e => {\n            self.fire('play', e); // check for the start time and start with it\n\n            if (self.options.startTime && e.seconds === 0) {\n              self.play(self.options.startTime);\n            }\n          });\n          self.player.on('pause', e => {\n            self.fire('pause', e);\n          });\n          self.player.on('ended', e => {\n            self.fire('ended', e);\n          });\n          self.player.on('loaded', e => {\n            self.fire('ready', e);\n          });\n          self.player.on('volumechange', e => {\n            self.fire('volumechange', e);\n          });\n          self.player.on('error', e => {\n            self.fire('error', e);\n          });\n        } // Local\n\n\n        function addSourceToLocal(element, src, type) {\n          const source = document.createElement('source');\n          source.src = src;\n          source.type = type;\n          element.appendChild(source);\n        }\n\n        if (self.type === 'local') {\n          if (!self.$video) {\n            self.$video = document.createElement('video'); // show controls\n\n            if (self.options.showControls) {\n              self.$video.controls = true;\n            } // mute\n\n\n            if (self.options.mute) {\n              self.$video.muted = true;\n            } else if (self.$video.volume) {\n              self.$video.volume = self.options.volume / 100;\n            } // loop\n\n\n            if (self.options.loop) {\n              self.$video.loop = true;\n            } // autoplay enable on mobile devices\n\n\n            self.$video.setAttribute('playsinline', '');\n            self.$video.setAttribute('webkit-playsinline', ''); // add accessibility attributes\n\n            if (self.options.accessibilityHidden) {\n              self.$video.setAttribute('tabindex', '-1');\n              self.$video.setAttribute('aria-hidden', 'true');\n            }\n\n            self.$video.setAttribute('id', self.playerID);\n            hiddenDiv.appendChild(self.$video);\n            document.body.appendChild(hiddenDiv);\n            Object.keys(self.videoID).forEach(key => {\n              addSourceToLocal(self.$video, self.videoID[key], `video/${key}`);\n            });\n          }\n\n          self.player = self.player || self.$video;\n          let locStarted;\n          self.player.addEventListener('playing', e => {\n            if (!locStarted) {\n              self.fire('started', e);\n            }\n\n            locStarted = 1;\n          });\n          self.player.addEventListener('timeupdate', function (e) {\n            self.fire('timeupdate', e); // check for end of video and play again or stop\n\n            if (self.options.endTime) {\n              if (self.options.endTime && this.currentTime >= self.options.endTime) {\n                if (self.options.loop) {\n                  self.play(self.options.startTime);\n                } else {\n                  self.pause();\n                }\n              }\n            }\n          });\n          self.player.addEventListener('play', e => {\n            self.fire('play', e);\n          });\n          self.player.addEventListener('pause', e => {\n            self.fire('pause', e);\n          });\n          self.player.addEventListener('ended', e => {\n            self.fire('ended', e);\n          });\n          self.player.addEventListener('loadedmetadata', function () {\n            // get video width and height\n            self.videoWidth = this.videoWidth || 1280;\n            self.videoHeight = this.videoHeight || 720;\n            self.fire('ready'); // autoplay\n\n            if (self.options.autoplay) {\n              self.play(self.options.startTime);\n            }\n          });\n          self.player.addEventListener('volumechange', e => {\n            self.getVolume(volume => {\n              self.options.volume = volume;\n            });\n            self.fire('volumechange', e);\n          });\n          self.player.addEventListener('error', e => {\n            self.fire('error', e);\n          });\n        }\n\n        callback(self.$video);\n      });\n    }\n\n    init() {\n      const self = this;\n      self.playerID = `VideoWorker-${self.ID}`;\n    }\n\n    loadAPI() {\n      const self = this;\n\n      if (YoutubeAPIadded && VimeoAPIadded) {\n        return;\n      }\n\n      let src = ''; // load Youtube API\n\n      if (self.type === 'youtube' && !YoutubeAPIadded) {\n        YoutubeAPIadded = 1;\n        src = 'https://www.youtube.com/iframe_api';\n      } // load Vimeo API\n\n\n      if (self.type === 'vimeo' && !VimeoAPIadded) {\n        VimeoAPIadded = 1; // Useful when Vimeo API added using RequireJS https://github.com/nk-o/video-worker/pull/7\n\n        if (typeof global$1$1.Vimeo !== 'undefined') {\n          return;\n        }\n\n        src = 'https://player.vimeo.com/api/player.js';\n      }\n\n      if (!src) {\n        return;\n      } // add script in head section\n\n\n      let tag = document.createElement('script');\n      let head = document.getElementsByTagName('head')[0];\n      tag.src = src;\n      head.appendChild(tag);\n      head = null;\n      tag = null;\n    }\n\n    onAPIready(callback) {\n      const self = this; // Youtube\n\n      if (self.type === 'youtube') {\n        // Listen for global YT player callback\n        if ((typeof global$1$1.YT === 'undefined' || global$1$1.YT.loaded === 0) && !loadingYoutubePlayer) {\n          // Prevents Ready event from being called twice\n          loadingYoutubePlayer = 1; // Creates deferred so, other players know when to wait.\n\n          global$1$1.onYouTubeIframeAPIReady = function () {\n            global$1$1.onYouTubeIframeAPIReady = null;\n            loadingYoutubeDefer.resolve('done');\n            callback();\n          };\n        } else if (typeof global$1$1.YT === 'object' && global$1$1.YT.loaded === 1) {\n          callback();\n        } else {\n          loadingYoutubeDefer.done(() => {\n            callback();\n          });\n        }\n      } // Vimeo\n\n\n      if (self.type === 'vimeo') {\n        if (typeof global$1$1.Vimeo === 'undefined' && !loadingVimeoPlayer) {\n          loadingVimeoPlayer = 1;\n          const vimeoInterval = setInterval(() => {\n            if (typeof global$1$1.Vimeo !== 'undefined') {\n              clearInterval(vimeoInterval);\n              loadingVimeoDefer.resolve('done');\n              callback();\n            }\n          }, 20);\n        } else if (typeof global$1$1.Vimeo !== 'undefined') {\n          callback();\n        } else {\n          loadingVimeoDefer.done(() => {\n            callback();\n          });\n        }\n      } // Local\n\n\n      if (self.type === 'local') {\n        callback();\n      }\n    }\n\n  }\n\n  function ready(callback) {\n    if ('complete' === document.readyState || 'interactive' === document.readyState) {\n      // Already ready or interactive, execute callback\n      callback();\n    } else {\n      document.addEventListener('DOMContentLoaded', callback, {\n        capture: true,\n        once: true,\n        passive: true\n      });\n    }\n  }\n\n  /* eslint-disable import/no-mutable-exports */\n\n  /* eslint-disable no-restricted-globals */\n  let win;\n\n  if ('undefined' !== typeof window) {\n    win = window;\n  } else if ('undefined' !== typeof global) {\n    win = global;\n  } else if ('undefined' !== typeof self) {\n    win = self;\n  } else {\n    win = {};\n  }\n\n  var global$1 = win;\n\n  function jarallaxVideo(jarallax = global$1.jarallax) {\n    if ('undefined' === typeof jarallax) {\n      return;\n    }\n\n    const Jarallax = jarallax.constructor; // append video after when block will be visible.\n\n    const defOnScroll = Jarallax.prototype.onScroll;\n\n    Jarallax.prototype.onScroll = function () {\n      const self = this;\n      defOnScroll.apply(self);\n      const isReady = !self.isVideoInserted && self.video && (!self.options.videoLazyLoading || self.isElementInViewport) && !self.options.disableVideo();\n\n      if (isReady) {\n        self.isVideoInserted = true;\n        self.video.getVideo(video => {\n          const $parent = video.parentNode;\n          self.css(video, {\n            position: self.image.position,\n            top: '0px',\n            left: '0px',\n            right: '0px',\n            bottom: '0px',\n            width: '100%',\n            height: '100%',\n            maxWidth: 'none',\n            maxHeight: 'none',\n            pointerEvents: 'none',\n            transformStyle: 'preserve-3d',\n            backfaceVisibility: 'hidden',\n            willChange: 'transform,opacity',\n            margin: 0,\n            zIndex: -1\n          });\n          self.$video = video; // add Poster attribute to self-hosted video\n\n          if ('local' === self.video.type) {\n            if (self.image.src) {\n              self.$video.setAttribute('poster', self.image.src);\n            } else if (self.image.$item && 'IMG' === self.image.$item.tagName && self.image.$item.src) {\n              self.$video.setAttribute('poster', self.image.$item.src);\n            }\n          } // insert video tag\n\n\n          self.image.$container.appendChild(video); // remove parent video element (created by VideoWorker)\n\n          $parent.parentNode.removeChild($parent); // call onVideoInsert event\n\n          if (self.options.onVideoInsert) {\n            self.options.onVideoInsert.call(self);\n          }\n        });\n      }\n    }; // cover video\n\n\n    const defCoverImage = Jarallax.prototype.coverImage;\n\n    Jarallax.prototype.coverImage = function () {\n      const self = this;\n      const imageData = defCoverImage.apply(self);\n      const node = self.image.$item ? self.image.$item.nodeName : false;\n\n      if (imageData && self.video && node && ('IFRAME' === node || 'VIDEO' === node)) {\n        let h = imageData.image.height;\n        let w = h * self.image.width / self.image.height;\n        let ml = (imageData.container.width - w) / 2;\n        let mt = imageData.image.marginTop;\n\n        if (imageData.container.width > w) {\n          w = imageData.container.width;\n          h = w * self.image.height / self.image.width;\n          ml = 0;\n          mt += (imageData.image.height - h) / 2;\n        } // add video height over than need to hide controls\n\n\n        if ('IFRAME' === node) {\n          h += 400;\n          mt -= 200;\n        }\n\n        self.css(self.$video, {\n          width: `${w}px`,\n          marginLeft: `${ml}px`,\n          height: `${h}px`,\n          marginTop: `${mt}px`\n        });\n      }\n\n      return imageData;\n    }; // init video\n\n\n    const defInitImg = Jarallax.prototype.initImg;\n\n    Jarallax.prototype.initImg = function () {\n      const self = this;\n      const defaultResult = defInitImg.apply(self);\n\n      if (!self.options.videoSrc) {\n        self.options.videoSrc = self.$item.getAttribute('data-jarallax-video') || null;\n      }\n\n      if (self.options.videoSrc) {\n        self.defaultInitImgResult = defaultResult;\n        return true;\n      }\n\n      return defaultResult;\n    };\n\n    const defCanInitParallax = Jarallax.prototype.canInitParallax;\n\n    Jarallax.prototype.canInitParallax = function () {\n      const self = this;\n      let defaultResult = defCanInitParallax.apply(self);\n\n      if (!self.options.videoSrc) {\n        return defaultResult;\n      } // Init video api\n\n\n      const video = new VideoWorker(self.options.videoSrc, {\n        autoplay: true,\n        loop: self.options.videoLoop,\n        showControls: false,\n        accessibilityHidden: true,\n        startTime: self.options.videoStartTime || 0,\n        endTime: self.options.videoEndTime || 0,\n        mute: self.options.videoVolume ? 0 : 1,\n        volume: self.options.videoVolume || 0\n      }); // call onVideoWorkerInit event\n\n      if (self.options.onVideoWorkerInit) {\n        self.options.onVideoWorkerInit.call(self, video);\n      }\n\n      function resetDefaultImage() {\n        if (self.image.$default_item) {\n          self.image.$item = self.image.$default_item;\n          self.image.$item.style.display = 'block'; // set image width and height\n\n          self.coverImage();\n          self.onScroll();\n        }\n      }\n\n      if (video.isValid()) {\n        // Force enable parallax.\n        // When the parallax disabled on mobile devices, we still need to display videos.\n        // https://github.com/nk-o/jarallax/issues/159\n        if (this.options.disableParallax()) {\n          defaultResult = true;\n          self.image.position = 'absolute';\n          self.options.type = 'scroll';\n          self.options.speed = 1;\n        } // if parallax will not be inited, we can add thumbnail on background.\n\n\n        if (!defaultResult) {\n          if (!self.defaultInitImgResult) {\n            video.getImageURL(url => {\n              // save default user styles\n              const curStyle = self.$item.getAttribute('style');\n\n              if (curStyle) {\n                self.$item.setAttribute('data-jarallax-original-styles', curStyle);\n              } // set new background\n\n\n              self.css(self.$item, {\n                'background-image': `url(\"${url}\")`,\n                'background-position': 'center',\n                'background-size': 'cover'\n              });\n            });\n          } // init video\n\n        } else {\n          video.on('ready', () => {\n            if (self.options.videoPlayOnlyVisible) {\n              const oldOnScroll = self.onScroll;\n\n              self.onScroll = function () {\n                oldOnScroll.apply(self);\n\n                if (!self.videoError && (self.options.videoLoop || !self.options.videoLoop && !self.videoEnded)) {\n                  if (self.isVisible()) {\n                    video.play();\n                  } else {\n                    video.pause();\n                  }\n                }\n              };\n            } else {\n              video.play();\n            }\n          });\n          video.on('started', () => {\n            self.image.$default_item = self.image.$item;\n            self.image.$item = self.$video; // set video width and height\n\n            self.image.width = self.video.videoWidth || 1280;\n            self.image.height = self.video.videoHeight || 720;\n            self.coverImage();\n            self.onScroll(); // hide image\n\n            if (self.image.$default_item) {\n              self.image.$default_item.style.display = 'none';\n            }\n          });\n          video.on('ended', () => {\n            self.videoEnded = true;\n\n            if (!self.options.videoLoop) {\n              // show default image if Loop disabled.\n              resetDefaultImage();\n            }\n          });\n          video.on('error', () => {\n            self.videoError = true; // show default image if video loading error.\n\n            resetDefaultImage();\n          });\n          self.video = video; // set image if not exists\n\n          if (!self.defaultInitImgResult) {\n            // set empty image on self-hosted video if not defined\n            self.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n\n            if ('local' !== video.type) {\n              video.getImageURL(url => {\n                self.image.bgImage = `url(\"${url}\")`;\n                self.init();\n              });\n              return false;\n            }\n          }\n        }\n      }\n\n      return defaultResult;\n    }; // Destroy video parallax\n\n\n    const defDestroy = Jarallax.prototype.destroy;\n\n    Jarallax.prototype.destroy = function () {\n      const self = this;\n\n      if (self.image.$default_item) {\n        self.image.$item = self.image.$default_item;\n        delete self.image.$default_item;\n      }\n\n      defDestroy.apply(self);\n    };\n  }\n\n  jarallaxVideo(); // data-jarallax-video initialization\n\n  ready(() => {\n    if ('undefined' !== typeof global$1.jarallax) {\n      global$1.jarallax(document.querySelectorAll('[data-jarallax-video]'));\n    }\n  }); // We should add VideoWorker globally, since some project uses it.\n\n  if (!global$1.VideoWorker) {\n    global$1.VideoWorker = VideoWorker;\n  }\n\n  return jarallaxVideo;\n\n}));\n//# sourceMappingURL=jarallax-video.js.map\n","Magento_PageBuilder/js/resource/jarallax/jarallax-wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_PageBuilder/js/resource/jarallax/jarallax'\n], function(jarallax){\n    'use strict';\n\n    window.jarallax = window.jarallax || jarallax;\n});\n","Magento_PageBuilder/js/resource/jarallax/jarallax.js":"/*!\n * Jarallax v2.0.3 (https://github.com/nk-o/jarallax)\n * Copyright 2022 nK <https://nkdev.info>\n * Licensed under MIT (https://github.com/nk-o/jarallax/blob/master/LICENSE)\n */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n      typeof define === 'function' && define.amd ? define(factory) :\n          (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.jarallax = factory());\n})(this, (function () { 'use strict';\n\n  function ready(callback) {\n    if ('complete' === document.readyState || 'interactive' === document.readyState) {\n      // Already ready or interactive, execute callback\n      callback();\n    } else {\n      document.addEventListener('DOMContentLoaded', callback, {\n        capture: true,\n        once: true,\n        passive: true\n      });\n    }\n  }\n\n  /* eslint-disable import/no-mutable-exports */\n\n  /* eslint-disable no-restricted-globals */\n  let win;\n\n  if ('undefined' !== typeof window) {\n    win = window;\n  } else if ('undefined' !== typeof global) {\n    win = global;\n  } else if ('undefined' !== typeof self) {\n    win = self;\n  } else {\n    win = {};\n  }\n\n  var global$1 = win;\n\n  const {\n    navigator\n  } = global$1;\n  const isMobile = /*#__PURE__*/ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n  let $deviceHelper;\n  /**\n   * The most popular mobile browsers changes height after page scroll and this generates image jumping.\n   * We can fix it using this workaround with vh units.\n   */\n\n  function getDeviceHeight() {\n    if (!$deviceHelper && document.body) {\n      $deviceHelper = document.createElement('div');\n      $deviceHelper.style.cssText = 'position: fixed; top: -9999px; left: 0; height: 100vh; width: 0;';\n      document.body.appendChild($deviceHelper);\n    }\n\n    return ($deviceHelper ? $deviceHelper.clientHeight : 0) || global$1.innerHeight || document.documentElement.clientHeight;\n  } // Window height data\n\n\n  let wndH;\n\n  function updateWndVars() {\n    if (isMobile) {\n      wndH = getDeviceHeight();\n    } else {\n      wndH = global$1.innerHeight || document.documentElement.clientHeight;\n    }\n  }\n\n  updateWndVars();\n  global$1.addEventListener('resize', updateWndVars);\n  global$1.addEventListener('orientationchange', updateWndVars);\n  global$1.addEventListener('load', updateWndVars);\n  ready(() => {\n    updateWndVars();\n  }); // list with all jarallax instances\n  // need to render all in one scroll/resize event\n\n  const jarallaxList = []; // get all parents of the element.\n\n  function getParents(elem) {\n    const parents = [];\n\n    while (null !== elem.parentElement) {\n      elem = elem.parentElement;\n\n      if (1 === elem.nodeType) {\n        parents.push(elem);\n      }\n    }\n\n    return parents;\n  }\n\n  function updateParallax() {\n    if (!jarallaxList.length) {\n      return;\n    }\n\n    jarallaxList.forEach((data, k) => {\n      const {\n        instance,\n        oldData\n      } = data;\n      const clientRect = instance.$item.getBoundingClientRect();\n      const newData = {\n        width: clientRect.width,\n        height: clientRect.height,\n        top: clientRect.top,\n        bottom: clientRect.bottom,\n        wndW: global$1.innerWidth,\n        wndH\n      };\n      const isResized = !oldData || oldData.wndW !== newData.wndW || oldData.wndH !== newData.wndH || oldData.width !== newData.width || oldData.height !== newData.height;\n      const isScrolled = isResized || !oldData || oldData.top !== newData.top || oldData.bottom !== newData.bottom;\n      jarallaxList[k].oldData = newData;\n\n      if (isResized) {\n        instance.onResize();\n      }\n\n      if (isScrolled) {\n        instance.onScroll();\n      }\n    });\n    global$1.requestAnimationFrame(updateParallax);\n  }\n\n  let instanceID = 0; // Jarallax class\n\n  class Jarallax {\n    constructor(item, userOptions) {\n      const self = this;\n      self.instanceID = instanceID;\n      instanceID += 1;\n      self.$item = item;\n      self.defaults = {\n        type: 'scroll',\n        // type of parallax: scroll, scale, opacity, scale-opacity, scroll-opacity\n        speed: 0.5,\n        // supported value from -1 to 2\n        imgSrc: null,\n        imgElement: '.jarallax-img',\n        imgSize: 'cover',\n        imgPosition: '50% 50%',\n        imgRepeat: 'no-repeat',\n        // supported only for background, not for <img> tag\n        keepImg: false,\n        // keep <img> tag in it's default place\n        elementInViewport: null,\n        zIndex: -100,\n        disableParallax: false,\n        disableVideo: false,\n        // video\n        videoSrc: null,\n        videoStartTime: 0,\n        videoEndTime: 0,\n        videoVolume: 0,\n        videoLoop: true,\n        videoPlayOnlyVisible: true,\n        videoLazyLoading: true,\n        // events\n        onScroll: null,\n        // function(calculations) {}\n        onInit: null,\n        // function() {}\n        onDestroy: null,\n        // function() {}\n        onCoverImage: null // function() {}\n\n      }; // prepare data-options\n\n      const dataOptions = self.$item.dataset || {};\n      const pureDataOptions = {};\n      Object.keys(dataOptions).forEach(key => {\n        const loweCaseOption = key.substr(0, 1).toLowerCase() + key.substr(1);\n\n        if (loweCaseOption && 'undefined' !== typeof self.defaults[loweCaseOption]) {\n          pureDataOptions[loweCaseOption] = dataOptions[key];\n        }\n      });\n      self.options = self.extend({}, self.defaults, pureDataOptions, userOptions);\n      self.pureOptions = self.extend({}, self.options); // prepare 'true' and 'false' strings to boolean\n\n      Object.keys(self.options).forEach(key => {\n        if ('true' === self.options[key]) {\n          self.options[key] = true;\n        } else if ('false' === self.options[key]) {\n          self.options[key] = false;\n        }\n      }); // fix speed option [-1.0, 2.0]\n\n      self.options.speed = Math.min(2, Math.max(-1, parseFloat(self.options.speed))); // prepare disableParallax callback\n\n      if ('string' === typeof self.options.disableParallax) {\n        self.options.disableParallax = new RegExp(self.options.disableParallax);\n      }\n\n      if (self.options.disableParallax instanceof RegExp) {\n        const disableParallaxRegexp = self.options.disableParallax;\n\n        self.options.disableParallax = () => disableParallaxRegexp.test(navigator.userAgent);\n      }\n\n      if ('function' !== typeof self.options.disableParallax) {\n        self.options.disableParallax = () => false;\n      } // prepare disableVideo callback\n\n\n      if ('string' === typeof self.options.disableVideo) {\n        self.options.disableVideo = new RegExp(self.options.disableVideo);\n      }\n\n      if (self.options.disableVideo instanceof RegExp) {\n        const disableVideoRegexp = self.options.disableVideo;\n\n        self.options.disableVideo = () => disableVideoRegexp.test(navigator.userAgent);\n      }\n\n      if ('function' !== typeof self.options.disableVideo) {\n        self.options.disableVideo = () => false;\n      } // custom element to check if parallax in viewport\n\n\n      let elementInVP = self.options.elementInViewport; // get first item from array\n\n      if (elementInVP && 'object' === typeof elementInVP && 'undefined' !== typeof elementInVP.length) {\n        [elementInVP] = elementInVP;\n      } // check if dom element\n\n\n      if (!(elementInVP instanceof Element)) {\n        elementInVP = null;\n      }\n\n      self.options.elementInViewport = elementInVP;\n      self.image = {\n        src: self.options.imgSrc || null,\n        $container: null,\n        useImgTag: false,\n        // 1. Position fixed is needed for the most of browsers because absolute position have glitches\n        // 2. On MacOS with smooth scroll there is a huge lags with absolute position - https://github.com/nk-o/jarallax/issues/75\n        // 3. Previously used 'absolute' for mobile devices. But we re-tested on iPhone 12 and 'fixed' position is working better, then 'absolute', so for now position is always 'fixed'\n        position: 'fixed'\n      };\n\n      if (self.initImg() && self.canInitParallax()) {\n        self.init();\n      }\n    } // add styles to element\n    // eslint-disable-next-line class-methods-use-this\n\n\n    css(el, styles) {\n      if ('string' === typeof styles) {\n        return global$1.getComputedStyle(el).getPropertyValue(styles);\n      }\n\n      Object.keys(styles).forEach(key => {\n        el.style[key] = styles[key];\n      });\n      return el;\n    } // Extend like jQuery.extend\n    // eslint-disable-next-line class-methods-use-this\n\n\n    extend(out, ...args) {\n      out = out || {};\n      Object.keys(args).forEach(i => {\n        if (!args[i]) {\n          return;\n        }\n\n        Object.keys(args[i]).forEach(key => {\n          out[key] = args[i][key];\n        });\n      });\n      return out;\n    } // get window size and scroll position. Useful for extensions\n    // eslint-disable-next-line class-methods-use-this\n\n\n    getWindowData() {\n      return {\n        width: global$1.innerWidth || document.documentElement.clientWidth,\n        height: wndH,\n        y: document.documentElement.scrollTop\n      };\n    } // Jarallax functions\n\n\n    initImg() {\n      const self = this; // find image element\n\n      let $imgElement = self.options.imgElement;\n\n      if ($imgElement && 'string' === typeof $imgElement) {\n        $imgElement = self.$item.querySelector($imgElement);\n      } // check if dom element\n\n\n      if (!($imgElement instanceof Element)) {\n        if (self.options.imgSrc) {\n          $imgElement = new Image();\n          $imgElement.src = self.options.imgSrc;\n        } else {\n          $imgElement = null;\n        }\n      }\n\n      if ($imgElement) {\n        if (self.options.keepImg) {\n          self.image.$item = $imgElement.cloneNode(true);\n        } else {\n          self.image.$item = $imgElement;\n          self.image.$itemParent = $imgElement.parentNode;\n        }\n\n        self.image.useImgTag = true;\n      } // true if there is img tag\n\n\n      if (self.image.$item) {\n        return true;\n      } // get image src\n\n\n      if (null === self.image.src) {\n        self.image.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n        self.image.bgImage = self.css(self.$item, 'background-image');\n      }\n\n      return !(!self.image.bgImage || 'none' === self.image.bgImage);\n    }\n\n    canInitParallax() {\n      return !this.options.disableParallax();\n    }\n\n    init() {\n      const self = this;\n      const containerStyles = {\n        position: 'absolute',\n        top: 0,\n        left: 0,\n        width: '100%',\n        height: '100%',\n        overflow: 'hidden'\n      };\n      let imageStyles = {\n        pointerEvents: 'none',\n        transformStyle: 'preserve-3d',\n        backfaceVisibility: 'hidden',\n        willChange: 'transform,opacity'\n      };\n\n      if (!self.options.keepImg) {\n        // save default user styles\n        const curStyle = self.$item.getAttribute('style');\n\n        if (curStyle) {\n          self.$item.setAttribute('data-jarallax-original-styles', curStyle);\n        }\n\n        if (self.image.useImgTag) {\n          const curImgStyle = self.image.$item.getAttribute('style');\n\n          if (curImgStyle) {\n            self.image.$item.setAttribute('data-jarallax-original-styles', curImgStyle);\n          }\n        }\n      } // set relative position and z-index to the parent\n\n\n      if ('static' === self.css(self.$item, 'position')) {\n        self.css(self.$item, {\n          position: 'relative'\n        });\n      }\n\n      if ('auto' === self.css(self.$item, 'z-index')) {\n        self.css(self.$item, {\n          zIndex: 0\n        });\n      } // container for parallax image\n\n\n      self.image.$container = document.createElement('div');\n      self.css(self.image.$container, containerStyles);\n      self.css(self.image.$container, {\n        'z-index': self.options.zIndex\n      }); // it will remove some image overlapping\n      // overlapping occur due to an image position fixed inside absolute position element\n      // needed only when background in fixed position\n\n      if ('fixed' === this.image.position) {\n        self.css(self.image.$container, {\n          '-webkit-clip-path': 'polygon(0 0, 100% 0, 100% 100%, 0 100%)',\n          'clip-path': 'polygon(0 0, 100% 0, 100% 100%, 0 100%)'\n        });\n      }\n\n      self.image.$container.setAttribute('id', `jarallax-container-${self.instanceID}`);\n      self.$item.appendChild(self.image.$container); // use img tag\n\n      if (self.image.useImgTag) {\n        imageStyles = self.extend({\n          'object-fit': self.options.imgSize,\n          'object-position': self.options.imgPosition,\n          'max-width': 'none'\n        }, containerStyles, imageStyles); // use div with background image\n      } else {\n        self.image.$item = document.createElement('div');\n\n        if (self.image.src) {\n          imageStyles = self.extend({\n            'background-position': self.options.imgPosition,\n            'background-size': self.options.imgSize,\n            'background-repeat': self.options.imgRepeat,\n            'background-image': self.image.bgImage || `url(\"${self.image.src}\")`\n          }, containerStyles, imageStyles);\n        }\n      }\n\n      if ('opacity' === self.options.type || 'scale' === self.options.type || 'scale-opacity' === self.options.type || 1 === self.options.speed) {\n        self.image.position = 'absolute';\n      } // 1. Check if one of parents have transform style (without this check, scroll transform will be inverted if used parallax with position fixed)\n      //    discussion - https://github.com/nk-o/jarallax/issues/9\n      // 2. Check if parents have overflow scroll\n\n\n      if ('fixed' === self.image.position) {\n        const $parents = getParents(self.$item).filter(el => {\n          const styles = global$1.getComputedStyle(el);\n          const parentTransform = styles['-webkit-transform'] || styles['-moz-transform'] || styles.transform;\n          const overflowRegex = /(auto|scroll)/;\n          return parentTransform && 'none' !== parentTransform || overflowRegex.test(styles.overflow + styles['overflow-y'] + styles['overflow-x']);\n        });\n        self.image.position = $parents.length ? 'absolute' : 'fixed';\n      } // add position to parallax block\n\n\n      imageStyles.position = self.image.position; // insert parallax image\n\n      self.css(self.image.$item, imageStyles);\n      self.image.$container.appendChild(self.image.$item); // set initial position and size\n\n      self.onResize();\n      self.onScroll(true); // call onInit event\n\n      if (self.options.onInit) {\n        self.options.onInit.call(self);\n      } // remove default user background\n\n\n      if ('none' !== self.css(self.$item, 'background-image')) {\n        self.css(self.$item, {\n          'background-image': 'none'\n        });\n      }\n\n      self.addToParallaxList();\n    } // add to parallax instances list\n\n\n    addToParallaxList() {\n      jarallaxList.push({\n        instance: this\n      });\n\n      if (1 === jarallaxList.length) {\n        global$1.requestAnimationFrame(updateParallax);\n      }\n    } // remove from parallax instances list\n\n\n    removeFromParallaxList() {\n      const self = this;\n      jarallaxList.forEach((data, key) => {\n        if (data.instance.instanceID === self.instanceID) {\n          jarallaxList.splice(key, 1);\n        }\n      });\n    }\n\n    destroy() {\n      const self = this;\n      self.removeFromParallaxList(); // return styles on container as before jarallax init\n\n      const originalStylesTag = self.$item.getAttribute('data-jarallax-original-styles');\n      self.$item.removeAttribute('data-jarallax-original-styles'); // null occurs if there is no style tag before jarallax init\n\n      if (!originalStylesTag) {\n        self.$item.removeAttribute('style');\n      } else {\n        self.$item.setAttribute('style', originalStylesTag);\n      }\n\n      if (self.image.useImgTag) {\n        // return styles on img tag as before jarallax init\n        const originalStylesImgTag = self.image.$item.getAttribute('data-jarallax-original-styles');\n        self.image.$item.removeAttribute('data-jarallax-original-styles'); // null occurs if there is no style tag before jarallax init\n\n        if (!originalStylesImgTag) {\n          self.image.$item.removeAttribute('style');\n        } else {\n          self.image.$item.setAttribute('style', originalStylesTag);\n        } // move img tag to its default position\n\n\n        if (self.image.$itemParent) {\n          self.image.$itemParent.appendChild(self.image.$item);\n        }\n      } // remove additional dom elements\n\n\n      if (self.image.$container) {\n        self.image.$container.parentNode.removeChild(self.image.$container);\n      } // call onDestroy event\n\n\n      if (self.options.onDestroy) {\n        self.options.onDestroy.call(self);\n      } // delete jarallax from item\n\n\n      delete self.$item.jarallax;\n    } // Fallback for removed function.\n    // Does nothing now.\n    // eslint-disable-next-line class-methods-use-this\n\n\n    clipContainer() {}\n\n    coverImage() {\n      const self = this;\n      const rect = self.image.$container.getBoundingClientRect();\n      const contH = rect.height;\n      const {\n        speed\n      } = self.options;\n      const isScroll = 'scroll' === self.options.type || 'scroll-opacity' === self.options.type;\n      let scrollDist = 0;\n      let resultH = contH;\n      let resultMT = 0; // scroll parallax\n\n      if (isScroll) {\n        // scroll distance and height for image\n        if (0 > speed) {\n          scrollDist = speed * Math.max(contH, wndH);\n\n          if (wndH < contH) {\n            scrollDist -= speed * (contH - wndH);\n          }\n        } else {\n          scrollDist = speed * (contH + wndH);\n        } // size for scroll parallax\n\n\n        if (1 < speed) {\n          resultH = Math.abs(scrollDist - wndH);\n        } else if (0 > speed) {\n          resultH = scrollDist / speed + Math.abs(scrollDist);\n        } else {\n          resultH += (wndH - contH) * (1 - speed);\n        }\n\n        scrollDist /= 2;\n      } // store scroll distance\n\n\n      self.parallaxScrollDistance = scrollDist; // vertical center\n\n      if (isScroll) {\n        resultMT = (wndH - resultH) / 2;\n      } else {\n        resultMT = (contH - resultH) / 2;\n      } // apply result to item\n\n\n      self.css(self.image.$item, {\n        height: `${resultH}px`,\n        marginTop: `${resultMT}px`,\n        left: 'fixed' === self.image.position ? `${rect.left}px` : '0',\n        width: `${rect.width}px`\n      }); // call onCoverImage event\n\n      if (self.options.onCoverImage) {\n        self.options.onCoverImage.call(self);\n      } // return some useful data. Used in the video cover function\n\n\n      return {\n        image: {\n          height: resultH,\n          marginTop: resultMT\n        },\n        container: rect\n      };\n    }\n\n    isVisible() {\n      return this.isElementInViewport || false;\n    }\n\n    onScroll(force) {\n      const self = this;\n      const rect = self.$item.getBoundingClientRect();\n      const contT = rect.top;\n      const contH = rect.height;\n      const styles = {}; // check if in viewport\n\n      let viewportRect = rect;\n\n      if (self.options.elementInViewport) {\n        viewportRect = self.options.elementInViewport.getBoundingClientRect();\n      }\n\n      self.isElementInViewport = 0 <= viewportRect.bottom && 0 <= viewportRect.right && viewportRect.top <= wndH && viewportRect.left <= global$1.innerWidth; // stop calculations if item is not in viewport\n\n      if (force ? false : !self.isElementInViewport) {\n        return;\n      } // calculate parallax helping variables\n\n\n      const beforeTop = Math.max(0, contT);\n      const beforeTopEnd = Math.max(0, contH + contT);\n      const afterTop = Math.max(0, -contT);\n      const beforeBottom = Math.max(0, contT + contH - wndH);\n      const beforeBottomEnd = Math.max(0, contH - (contT + contH - wndH));\n      const afterBottom = Math.max(0, -contT + wndH - contH);\n      const fromViewportCenter = 1 - 2 * ((wndH - contT) / (wndH + contH)); // calculate on how percent of section is visible\n\n      let visiblePercent = 1;\n\n      if (contH < wndH) {\n        visiblePercent = 1 - (afterTop || beforeBottom) / contH;\n      } else if (beforeTopEnd <= wndH) {\n        visiblePercent = beforeTopEnd / wndH;\n      } else if (beforeBottomEnd <= wndH) {\n        visiblePercent = beforeBottomEnd / wndH;\n      } // opacity\n\n\n      if ('opacity' === self.options.type || 'scale-opacity' === self.options.type || 'scroll-opacity' === self.options.type) {\n        styles.transform = 'translate3d(0,0,0)';\n        styles.opacity = visiblePercent;\n      } // scale\n\n\n      if ('scale' === self.options.type || 'scale-opacity' === self.options.type) {\n        let scale = 1;\n\n        if (0 > self.options.speed) {\n          scale -= self.options.speed * visiblePercent;\n        } else {\n          scale += self.options.speed * (1 - visiblePercent);\n        }\n\n        styles.transform = `scale(${scale}) translate3d(0,0,0)`;\n      } // scroll\n\n\n      if ('scroll' === self.options.type || 'scroll-opacity' === self.options.type) {\n        let positionY = self.parallaxScrollDistance * fromViewportCenter; // fix if parallax block in absolute position\n\n        if ('absolute' === self.image.position) {\n          positionY -= contT;\n        }\n\n        styles.transform = `translate3d(0,${positionY}px,0)`;\n      }\n\n      self.css(self.image.$item, styles); // call onScroll event\n\n      if (self.options.onScroll) {\n        self.options.onScroll.call(self, {\n          section: rect,\n          beforeTop,\n          beforeTopEnd,\n          afterTop,\n          beforeBottom,\n          beforeBottomEnd,\n          afterBottom,\n          visiblePercent,\n          fromViewportCenter\n        });\n      }\n    }\n\n    onResize() {\n      this.coverImage();\n    }\n\n  } // global definition\n\n\n  const jarallax = function (items, options, ...args) {\n    // check for dom element\n    // thanks: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object\n    if ('object' === typeof HTMLElement ? items instanceof HTMLElement : items && 'object' === typeof items && null !== items && 1 === items.nodeType && 'string' === typeof items.nodeName) {\n      items = [items];\n    }\n\n    const len = items.length;\n    let k = 0;\n    let ret;\n\n    for (k; k < len; k += 1) {\n      if ('object' === typeof options || 'undefined' === typeof options) {\n        if (!items[k].jarallax) {\n          items[k].jarallax = new Jarallax(items[k], options);\n        }\n      } else if (items[k].jarallax) {\n        // eslint-disable-next-line prefer-spread\n        ret = items[k].jarallax[options].apply(items[k].jarallax, args);\n      }\n\n      if ('undefined' !== typeof ret) {\n        return ret;\n      }\n    }\n\n    return items;\n  };\n\n  jarallax.constructor = Jarallax;\n\n  const $ = global$1.jQuery; // jQuery support\n\n  if ('undefined' !== typeof $) {\n    const $Plugin = function (...args) {\n      Array.prototype.unshift.call(args, this);\n      const res = jarallax.apply(global$1, args);\n      return 'object' !== typeof res ? res : this;\n    };\n\n    $Plugin.constructor = jarallax.constructor; // no conflict\n\n    const old$Plugin = $.fn.jarallax;\n    $.fn.jarallax = $Plugin;\n\n    $.fn.jarallax.noConflict = function () {\n      $.fn.jarallax = old$Plugin;\n      return this;\n    };\n  } // data-jarallax initialization\n\n\n  ready(() => {\n    jarallax(document.querySelectorAll('[data-jarallax]'));\n  });\n\n  return jarallax;\n\n}));\n//# sourceMappingURL=jarallax.js.map\n","Magento_PageBuilder/js/widget/show-on-hover.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['jquery'], function ($) {\n    'use strict';\n\n    /**\n     * Show the overlay on hover of specific elements\n     *\n     * @param {JQuery<Element>[]} $elements\n     */\n    function showOverlayOnHover($elements) {\n        $elements.each(function (index, element) {\n            var overlayEl = $(element).find('.pagebuilder-overlay'),\n                overlayColor = overlayEl.attr('data-overlay-color');\n\n            $(element).on('mouseenter', function () {\n                overlayEl.css('background-color', overlayColor);\n            });\n\n            $(element).on('mouseleave', function () {\n                overlayEl.css('background-color', 'transparent');\n            });\n        });\n    }\n\n    /**\n     * Show button on hover of specific elements\n     *\n     * @param {JQuery<Element>[]} $elements\n     * @param {String} buttonClass\n     */\n    function showButtonOnHover($elements, buttonClass) {\n        $elements.each(function (index, element) {\n            var buttonEl = $(element).find(buttonClass);\n\n            $(element).on('mouseenter', function () {\n                buttonEl.css({\n                    'opacity': '1',\n                    'visibility': 'visible'\n                });\n            });\n\n            $(element).on('mouseleave', function () {\n                buttonEl.css({\n                    'opacity': '0',\n                    'visibility': 'hidden'\n                });\n            });\n        });\n    }\n\n    return function (config) {\n\n        var buttonSelector = config.buttonSelector,\n            overlayHoverSelector = 'div[data-content-type=\"%s\"][data-show-overlay=\"%s\"]'\n                .replace('%s', config.dataRole)\n                .replace('%s', config.showOverlay),\n            overlayButtonSelector = 'div[data-content-type=\"%s\"][data-show-button=\"%s\"]'\n                .replace('%s', config.dataRole)\n                .replace('%s', config.showOverlay);\n\n        showOverlayOnHover($(overlayHoverSelector));\n        showButtonOnHover($(overlayButtonSelector), buttonSelector);\n    };\n});\n","Magento_PageBuilder/js/widget/video-background.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'jarallax',\n    'jarallaxVideo',\n    'vimeoWrapper'\n], function ($) {\n    'use strict';\n\n    return function (config, element) {\n        var $element = $(element),\n            parallaxSpeed = $element.data('enableParallax') !== 1 ? 1 : parseFloat($element.data('parallaxSpeed'));\n\n        if ($element.data('background-type') !== 'video') {\n            return;\n        }\n\n        $element.addClass('jarallax');\n        $element.attr('data-jarallax', '');\n\n        window.jarallax($element[0], {\n            imgSrc: $element.data('videoFallbackSrc'),\n            speed: !isNaN(parallaxSpeed) ? parallaxSpeed : 0.5,\n            videoLoop: $element.data('videoLoop'),\n            videoPlayOnlyVisible: $element.data('videoPlayOnlyVisible'),\n            videoLazyLoading: $element.data('videoLazyLoad'),\n            disableVideo: false,\n            elementInViewport: $element.data('elementInViewport') &&\n                $element[0].querySelector($element.data('elementInViewport'))\n        });\n        $element[0].jarallax.video && $element[0].jarallax.video.on('started', function () {\n            if ($element[0].jarallax.$video) {\n                $element[0].jarallax.$video.style.visibility = 'visible';\n            }\n        });\n    };\n});\n","Magento_PageBuilder/js/content-type/map/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/utils/map'\n], function ($, GoogleMap) {\n    'use strict';\n\n    return function (config, element) {\n        var locations,\n            controls,\n            mapOptions = {};\n\n        element = element[0];\n\n        if (element !== undefined && element.hasAttribute('data-locations')) {\n\n            /**\n             * Set map display to none if no locations\n             */\n            if (element.getAttribute('data-locations') === '[]') {\n                $(element).hide();\n\n                return;\n            }\n            locations = JSON.parse(element.getAttribute('data-locations'));\n            locations.forEach(function (location) {\n                location.position.latitude = parseFloat(location.position.latitude);\n                location.position.longitude = parseFloat(location.position.longitude);\n            });\n            controls = element.getAttribute('data-show-controls');\n            mapOptions.disableDefaultUI = controls !== 'true';\n            mapOptions.mapTypeControl = controls === 'true';\n            new GoogleMap(element, locations, mapOptions);\n        }\n    };\n});\n","Magento_PageBuilder/js/content-type/slide/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'underscore',\n    'Magento_PageBuilder/js/widget/show-on-hover',\n    'Magento_PageBuilder/js/widget/video-background'\n], function ($, _, showOnHover, videoBackground) {\n    'use strict';\n\n    return function (config, element) {\n        var videoElement = element[0].querySelector('[data-background-type=video]'),\n            viewportElement = document.createElement('div'),\n            $slider = null;\n\n        showOnHover(config);\n\n        if (videoElement) {\n            $slider = $(element).closest('[data-content-type=slider]');\n            viewportElement.classList.add('jarallax-viewport-element');\n            videoElement.setAttribute('data-element-in-viewport', '.jarallax-viewport-element');\n            videoElement.appendChild(viewportElement);\n            videoBackground(config, videoElement);\n\n            if ($slider.data('afterChangeIsSet')) {\n                return;\n            }\n\n            $slider.on('afterChange init', function () {\n                var videoSlides = $slider[0].querySelectorAll('.jarallax');\n\n                _.each(videoSlides, function (videoSlide) {\n                    videoSlide.jarallax && videoSlide.jarallax.onScroll();\n                });\n            });\n            $slider.data('afterChangeIsSet', true);\n        }\n    };\n});\n","Magento_PageBuilder/js/content-type/row/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/widget/video-background',\n    'jarallax'\n], function ($, videoBackground) {\n    'use strict';\n\n    return function (config, element) {\n        var $element = $(element),\n            parallaxSpeed = null,\n            elementStyle = null;\n\n        if ($element.data('appearance') === 'contained') {\n            $element = $(element).find('[data-element=\"inner\"]');\n        }\n\n        if ($element.data('background-type') === 'video') {\n            videoBackground(config, $element[0]);\n\n            return;\n        }\n\n        if ($element.data('enableParallax') !== 1) {\n            return;\n        }\n\n        $element.addClass('jarallax');\n        $element.attr('data-jarallax', '');\n\n        parallaxSpeed = parseFloat($element.data('parallaxSpeed'));\n        elementStyle = window.getComputedStyle($element[0]);\n\n        window.jarallax($element[0], {\n            imgPosition: elementStyle.backgroundPosition || '50% 50%',\n            imgRepeat: elementStyle.backgroundRepeat || 'no-repeat',\n            imgSize: elementStyle.backgroundSize || 'cover',\n            speed: !isNaN(parallaxSpeed) ? parallaxSpeed : 0.5\n        });\n    };\n});\n","Magento_PageBuilder/js/content-type/banner/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'Magento_PageBuilder/js/widget/show-on-hover',\n    'Magento_PageBuilder/js/widget/video-background'\n], function (showOnHover, videoBackground) {\n    'use strict';\n\n    return function (config, element) {\n        var videoElement = element[0].querySelector('[data-background-type=video]');\n\n        showOnHover(config);\n\n        if (videoElement) {\n            videoBackground(config, videoElement);\n        }\n    };\n});\n","Magento_PageBuilder/js/content-type/products/appearance/carousel/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'matchMedia',\n    'Magento_PageBuilder/js/utils/breakpoints',\n    'Magento_PageBuilder/js/events',\n    'slick'\n], function ($, _, mediaCheck, breakpointsUtils, events) {\n    'use strict';\n\n    /**\n     * Build slick\n     *\n     * @param {jQuery} $carouselElement\n     * @param {Object} config\n     */\n    function buildSlick($carouselElement, config) {\n        /**\n         * Prevent each slick slider from being initialized more than once which could throw an error.\n         */\n        if ($carouselElement.hasClass('slick-initialized')) {\n            $carouselElement.slick('unslick');\n        }\n\n        config.slidesToScroll = config.slidesToShow;\n        $carouselElement.slick(config);\n    }\n\n    /**\n     * Initialize slider.\n     *\n     * @param {jQuery} $element\n     * @param {Object} slickConfig\n     * @param {Object} breakpoint\n     */\n    function initSlider($element, slickConfig, breakpoint) {\n        var productCount = $element.find('.product-item').length,\n            $carouselElement = $($element.children()),\n            centerModeClass = 'center-mode',\n            carouselMode = $element.data('carousel-mode'),\n            slidesToShow = breakpoint.options.products[carouselMode] ?\n                breakpoint.options.products[carouselMode].slidesToShow :\n                breakpoint.options.products.default.slidesToShow;\n\n        slickConfig.slidesToShow = parseFloat(slidesToShow);\n\n        if (carouselMode === 'continuous' && productCount > slickConfig.slidesToShow) {\n            $element.addClass(centerModeClass);\n            slickConfig.centerPadding = $element.data('center-padding');\n            slickConfig.centerMode = true;\n        } else {\n            $element.removeClass(centerModeClass);\n            slickConfig.infinite = $element.data('infinite-loop');\n        }\n\n        buildSlick($carouselElement, slickConfig);\n    }\n\n    return function (config, element) {\n        var $element = $(element),\n            $carouselElement = $($element.children()),\n            currentViewport = config.currentViewport,\n            currentBreakpoint = config.breakpoints[currentViewport],\n            slickConfig = {\n                autoplay: $element.data('autoplay'),\n                autoplaySpeed: $element.data('autoplay-speed') || 0,\n                arrows: $element.data('show-arrows'),\n                dots: $element.data('show-dots')\n            };\n\n        _.each(config.breakpoints, function (breakpoint) {\n            mediaCheck({\n                media: breakpointsUtils.buildMedia(breakpoint.conditions),\n\n                /** @inheritdoc */\n                entry: function () {\n                    initSlider($element, slickConfig, breakpoint);\n                }\n            });\n        });\n\n        //initialize slider when content type is added in mobile viewport\n        if (currentViewport === 'mobile') {\n            initSlider($element, slickConfig, currentBreakpoint);\n        }\n\n        // Redraw slide after content type gets redrawn\n        events.on('contentType:redrawAfter', function (args) {\n            if ($carouselElement.closest(args.element).length) {\n                $carouselElement.slick('setPosition');\n            }\n        });\n\n        events.on('stage:viewportChangeAfter', function (args) {\n            var breakpoint = config.breakpoints[args.viewport];\n\n            initSlider($element, slickConfig, breakpoint);\n        });\n    };\n});\n","Magento_PageBuilder/js/content-type/tabs/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/events',\n    'jquery-ui-modules/tabs'\n], function ($, events) {\n    'use strict';\n\n    return function (config, element) {\n        var $element = $(element);\n\n        // Ignore stage builder preview tabs\n        if ($element.is('.pagebuilder-tabs')) {\n            return;\n        }\n\n        // Disambiguate between the mage/tabs component which is loaded randomly depending on requirejs order.\n        $.ui.tabs({\n            active: $element.data('activeTab') || 0,\n            create:\n\n                /**\n                 * Adjust the margin bottom of the navigation to correctly display the active tab\n                 */\n                function () {\n                    var borderWidth = parseInt($element.find('.tabs-content').css('borderWidth').toString(), 10);\n\n                    $element.find('.tabs-navigation').css('marginBottom', -borderWidth);\n                    $element.find('.tabs-navigation li:not(:first-child)').css('marginLeft', -borderWidth);\n                },\n            activate:\n\n                /**\n                 * Trigger redraw event since new content is being displayed\n                 */\n                function () {\n                    events.trigger('contentType:redrawAfter', {\n                        element: element\n                    });\n                }\n        }, element);\n    };\n});\n","Magento_PageBuilder/js/content-type/buttons/appearance/inline/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/events'\n], function ($, events) {\n    'use strict';\n\n    /**\n     * Equalize the width of a list of button-item components\n     *\n     * @param {JQuery} buttonList\n     */\n    var equalizeButtonWidth = function (buttonList) {\n        var buttonMinWidth = 0;\n\n        buttonList.css('min-width', buttonMinWidth);\n        buttonList.each(function () {\n            var buttonWidth = this.offsetWidth;\n\n            if (buttonWidth > buttonMinWidth) {\n                buttonMinWidth = buttonWidth;\n            }\n        });\n        buttonList.css('min-width', buttonMinWidth);\n    };\n\n    return function (config, element) {\n        var $element = $(element),\n            buttonSelector = '[data-element=\"link\"], [data-element=\"empty_link\"]';\n\n        if ($element.data('sameWidth')) {\n            equalizeButtonWidth($element.find(buttonSelector));\n            $(window).on('resize', function () {\n                equalizeButtonWidth($element.find(buttonSelector));\n            });\n            events.on('contentType:redrawAfter', function (eventData) {\n                if ($element.closest(eventData.element).length > 0) {\n                    equalizeButtonWidth($element.find(buttonSelector));\n                }\n            });\n        }\n    };\n});\n","Magento_PageBuilder/js/content-type/slider/appearance/default/widget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'Magento_PageBuilder/js/events',\n    'slick'\n], function ($, events) {\n    'use strict';\n\n    return function (config, sliderElement) {\n        var $element = $(sliderElement);\n\n        /**\n         * Prevent each slick slider from being initialized more than once which could throw an error.\n         */\n        if ($element.hasClass('slick-initialized')) {\n            $element.slick('unslick');\n        }\n\n        $element.slick({\n            autoplay: $element.data('autoplay'),\n            autoplaySpeed: $element.data('autoplay-speed') || 0,\n            fade: $element.data('fade'),\n            infinite: $element.data('infinite-loop'),\n            arrows: $element.data('show-arrows'),\n            dots: $element.data('show-dots')\n        });\n\n        // Redraw slide after content type gets redrawn\n        events.on('contentType:redrawAfter', function (args) {\n            if ($element.closest(args.element).length) {\n                $element.slick('setPosition');\n            }\n        });\n        // eslint-disable-next-line jquery-no-bind-unbind\n        events.on('stage:viewportChangeAfter', $element.slick.bind($element, 'setPosition'));\n    };\n});\n","Magento_PageBuilder/js/utils/map.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * googleMaps dependency is added within googlemaps.phtml through shim based on API key being set\n *\n * @api\n */\ndefine([\n    'underscore',\n    'module',\n    'Magento_PageBuilder/js/events'\n], function (_, module, events) {\n    'use strict';\n\n    var google = window.google || {},\n\n        /**\n         * Generates a google map usable latitude and longitude object\n         *\n         * @param {Object} position\n         * @return {google.maps.LatLng}\n         */\n        getGoogleLatitudeLongitude = function (position) {\n            return new google.maps.LatLng(position.latitude, position.longitude);\n        },\n        gmAuthFailure = false;\n\n    // jscs:disable requireCamelCaseOrUpperCaseIdentifiers\n    /**\n     * Google's error listener for map loader failures\n     */\n    window.gm_authFailure = function () {\n        events.trigger('googleMaps:authFailure');\n        gmAuthFailure = true;\n    };\n    // jscs:enable requireCamelCaseOrUpperCaseIdentifiers\n\n    return function (element, markers, additionalOptions) {\n        var options,\n            style;\n\n        // If we've previously had an API key error, throw the error even again\n        if (gmAuthFailure) {\n            events.trigger('googleMaps:authFailure');\n\n            return;\n        }\n\n        // If Google Maps isn't loaded don't try init the map, it won't work\n        if (typeof google.maps === 'undefined') {\n            return;\n        }\n\n        /**\n         * Just in case of a bad JSON that bypassed validation\n         */\n        try {\n            style = module.config().style ? JSON.parse(module.config().style) : [];\n        }\n        catch (error) {\n            style = [];\n        }\n        options = _.extend({\n            zoom: 8,\n            center: getGoogleLatitudeLongitude({\n                latitude: 30.2672,\n                longitude: -97.7431\n            }),\n            scrollwheel: false,\n            disableDoubleClickZoom: false,\n            disableDefaultUI: false,\n            mapTypeControl: true,\n            mapTypeControlOptions: {\n                style: google.maps.MapTypeControlStyle.DEFAULT\n            },\n            styles: style\n        }, additionalOptions);\n\n        /* Create the map */\n        this.map = new google.maps.Map(element, options);\n        this.markers = [];\n\n        /**\n         * Callback function on map config update\n         * @param {Array} newMarkers\n         * @param {Object} updateOptions\n         */\n        this.onUpdate = function (newMarkers, updateOptions) {\n            this.map.setOptions(updateOptions);\n            this.setMarkers(newMarkers);\n        };\n\n        /**\n         * Sets the markers to selected map\n         * @param {Object} newMarkers\n         */\n        this.setMarkers = function (newMarkers) {\n            var activeInfoWindow,\n                latitudeLongitudeBounds = new google.maps.LatLngBounds();\n\n            this.markers.forEach(function (marker) {\n                marker.setMap(null);\n            }, this);\n\n            this.markers = [];\n            this.bounds = [];\n\n            /**\n             * Creates and set listener for markers\n             */\n            if (newMarkers && newMarkers.length) {\n                newMarkers.forEach(function (newMarker) {\n                    var location = _.escape(newMarker['location_name']) || '',\n                    comment = newMarker.comment ?\n                        '<p>' + _.escape(newMarker.comment).replace(/(?:\\r\\n|\\r|\\n)/g, '<br/>') + '</p>'\n                        : '',\n                    phone = newMarker.phone ? '<p>Phone: ' + _.escape(newMarker.phone) + '</p>' : '',\n                    address = newMarker.address ? _.escape(newMarker.address) + '<br/>' : '',\n                    city = _.escape(newMarker.city) || '',\n                    country = newMarker.country ? _.escape(newMarker.country) : '',\n                    state = newMarker.state ? _.escape(newMarker.state) + ' ' : '',\n                    zipCode = newMarker.zipcode ? _.escape(newMarker.zipcode) : '',\n                    cityComma = city !== '' && (zipCode !== '' || state !== '') ? ', ' : '',\n                    lineBreak = city !== '' || zipCode !== '' ? '<br/>' : '',\n                    contentString =\n                        '<div>' +\n                        '<h3><b>' + location + '</b></h3>' +\n                        comment +\n                        phone +\n                        '<p><span>' + address +\n                        city + cityComma + state + zipCode + lineBreak +\n                        country + '</span></p>' +\n                        '</div>',\n                    infowindow = new google.maps.InfoWindow({\n                        content: contentString,\n                        maxWidth: 350\n                    }),\n                    newCreatedMarker = new google.maps.Marker({\n                        map: this.map,\n                        position: getGoogleLatitudeLongitude(newMarker.position),\n                        title: location\n                    });\n\n                    if (location) {\n                        newCreatedMarker.addListener('click', function () {\n                            if (activeInfoWindow) {\n                                activeInfoWindow.close();\n                            }\n\n                            infowindow.open(this.map, newCreatedMarker);\n                            activeInfoWindow = infowindow;\n                        }, this);\n                    }\n\n                    this.markers.push(newCreatedMarker);\n                    this.bounds.push(getGoogleLatitudeLongitude(newMarker.position));\n                }, this);\n            }\n\n            /**\n             * This sets the bounds of the map for multiple locations\n             */\n            if (this.bounds.length > 1) {\n                this.bounds.forEach(function (bound) {\n                    latitudeLongitudeBounds.extend(bound);\n                });\n                this.map.fitBounds(latitudeLongitudeBounds);\n            }\n\n            /**\n             * Zoom to 8 if there is only a single location\n             */\n            if (this.bounds.length === 1) {\n                this.map.setCenter(this.bounds[0]);\n                this.map.setZoom(8);\n            }\n        };\n\n        this.setMarkers(markers);\n    };\n});\n","Magento_PageBuilder/js/utils/breakpoints.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    return {\n        /**\n         * Build media query.\n         *\n         * @param {Object} conditions\n         * @returns {String}\n         */\n        buildMedia: function (conditions) {\n            var result = _.map(_.pairs(conditions), function (condition) {\n                return '(' + condition.join(': ') + ')';\n            });\n\n            return result.join(' and ');\n        }\n    };\n});\n","Magento_Downloadable/js/downloadable.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget',\n    'Magento_Catalog/js/price-box'\n], function ($) {\n    'use strict';\n\n    /**\n     * Downloadable widget\n     */\n    $.widget('mage.downloadable', {\n        options: {\n            priceHolderSelector: '.price-box',\n            linkElement: '',\n            allElements: ''\n        },\n\n        /**\n         * @inheritdoc\n         */\n        _init: function initLinks() {\n            var element = this.element,\n                options = $(this.options.linkElement, element);\n\n            options.trigger('change');\n        },\n\n        /**\n         *  @inheritdoc\n         */\n        _create: function () {\n            var self = this;\n\n            this.element.find(this.options.linkElement).on('change', $.proxy(function () {\n                this._reloadPrice();\n            }, this));\n\n            this.element.find(this.options.allElements).on('change', function () {\n                if (this.checked) {\n                    $('label[for=\"' + this.id + '\"] > span').text($(this).attr('data-checked'));\n                    self.element.find(self.options.linkElement + ':not(:checked)').each(function () {\n                        $(this).trigger('click');\n                    });\n                } else {\n                    $('[for=\"' + this.id + '\"] > span').text($(this).attr('data-notchecked'));\n                    self.element.find(self.options.linkElement + ':checked').each(function () {\n                        $(this).trigger('click');\n                    });\n                }\n            });\n\n            this._reloadPrice();\n        },\n\n        /**\n         * Reload product price with selected link price included\n         * @private\n         */\n        _reloadPrice: function () {\n            var finalPrice = 0,\n                basePrice = 0;\n\n            this.element.find(this.options.linkElement + ':checked').each($.proxy(function (index, element) {\n                finalPrice += this.options.config.links[$(element).val()].finalPrice;\n                basePrice += this.options.config.links[$(element).val()].basePrice;\n            }, this));\n\n            $(this.options.priceHolderSelector).trigger('updatePrice', {\n                'prices': {\n                    'finalPrice': {\n                        'amount': finalPrice\n                    },\n                    'basePrice': {\n                        'amount': basePrice\n                    }\n                }\n            });\n\n            this.reloadAllCheckText();\n        },\n\n        /**\n         * Reload all-elements-checkbox's label\n         * @private\n         */\n        reloadAllCheckText: function () {\n            var allChecked = true,\n                allElementsCheck = $(this.options.allElements),\n                allElementsLabel = $('label[for=\"' + allElementsCheck.attr('id') + '\"] > span');\n\n            $(this.options.linkElement).each(function () {\n                if (!this.checked) {\n                    allChecked = false;\n                }\n            });\n\n            if (allChecked) {\n                allElementsLabel.text(allElementsCheck.attr('data-checked'));\n                allElementsCheck.prop('checked', true);\n            } else {\n                allElementsLabel.text(allElementsCheck.attr('data-notchecked'));\n                allElementsCheck.prop('checked', false);\n            }\n        }\n    });\n\n    return $.mage.downloadable;\n});\n","Magento_ReCaptchaCheckout/js/reCaptchaCheckout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(\n    [\n        'Magento_ReCaptchaWebapiUi/js/webapiReCaptcha',\n        'jquery'\n    ],\n    function (Component, $) {\n        'use strict';\n\n        var reCaptchaIds = new WeakMap(),\n            uuid = 0;\n\n        return Component.extend({\n            defaults: {\n                template: 'Magento_ReCaptchaCheckout/reCaptcha',\n                skipPayments: [] // List of payment methods that do not require this reCaptcha\n            },\n\n            /**\n             * Render reCAPTCHA for payment method\n             *\n             * @param {Object} method\n             */\n            renderReCaptchaFor: function (method) {\n                var reCaptcha;\n\n                if (this.isCheckoutReCaptchaRequiredFor(method)) {\n                    reCaptcha = $.extend(true, {}, this, {reCaptchaId: this.getReCaptchaIdFor(method)});\n                    reCaptcha.renderReCaptcha();\n                }\n            },\n\n            /**\n             * Get reCAPTCHA ID for payment method\n             *\n             * @param {Object} method\n             * @returns {String}\n             */\n            getReCaptchaIdFor: function (method) {\n                if (!reCaptchaIds.has(method)) {\n                    reCaptchaIds.set(method, this.getReCaptchaId() + '-' + uuid++);\n                }\n                return reCaptchaIds.get(method);\n            },\n\n            /**\n             * Check whether checkout reCAPTCHA is required for payment method\n             *\n             * @param {Object} method\n             * @returns {Boolean}\n             */\n            isCheckoutReCaptchaRequiredFor: function (method) {\n                return !this.skipPayments || !this.skipPayments.hasOwnProperty(method.getCode());\n            },\n\n            /**\n             * @inheritdoc\n             */\n            initCaptcha: function () {\n                var $wrapper,\n                    $recaptchaResponseInput;\n\n                this._super();\n                // Since there will be multiple reCaptcha in the payment form,\n                // they may override each other if the form data is serialized and submitted.\n                // Instead, the reCaptcha response will be collected in the callback: reCaptchaCallback()\n                // and sent in the request header X-ReCaptcha\n                $wrapper = $('#' + this.getReCaptchaId() + '-wrapper');\n                $recaptchaResponseInput = $wrapper.find('[name=g-recaptcha-response]');\n                if ($recaptchaResponseInput.length) {\n                    $recaptchaResponseInput.prop('disabled', true);\n                }\n            }\n        });\n    }\n);\n","Magento_ReCaptchaCheckout/js/webapiReCaptchaRegistry-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return function (originalFunction) {\n        /**\n         * {@inheritDoc}\n         */\n       originalFunction.addListener = function (id , func) {\n            this._listeners[id] = func;\n       };\n\n        return originalFunction;\n    };\n\n});\n","Magento_ReCaptchaCheckout/js/model/place-order-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable max-nested-callbacks */\n\ndefine([\n    'jquery',\n    'mage/utils/wrapper',\n    'Magento_ReCaptchaWebapiUi/js/webapiReCaptchaRegistry'\n], function ($, wrapper, recaptchaRegistry) {\n    'use strict';\n\n    return function (placeOrder) {\n        return wrapper.wrap(placeOrder, function (originalAction, serviceUrl, payload, messageContainer) {\n            var recaptchaDeferred,\n                reCaptchaId,\n                $activeReCaptcha;\n\n            $activeReCaptcha = $('.recaptcha-checkout-place-order:visible .g-recaptcha');\n\n            if ($activeReCaptcha.length > 0) {\n                reCaptchaId = $activeReCaptcha.last().attr('id');\n            }\n\n            if (reCaptchaId !== undefined && recaptchaRegistry.triggers.hasOwnProperty(reCaptchaId)) {\n                //ReCaptcha is present for checkout\n                recaptchaDeferred = $.Deferred();\n                recaptchaRegistry.addListener(reCaptchaId, function (token) {\n                    //Add reCaptcha value to place-order request and resolve deferred with the API call results\n                    payload.xReCaptchaValue = token;\n                    originalAction(serviceUrl, payload, messageContainer).done(function () {\n                        recaptchaDeferred.resolve.apply(recaptchaDeferred, arguments);\n                    }).fail(function () {\n                        recaptchaDeferred.reject.apply(recaptchaDeferred, arguments);\n                    });\n                });\n                //Trigger ReCaptcha validation\n                recaptchaRegistry.triggers[reCaptchaId]();\n\n                if (\n                    !recaptchaRegistry._isInvisibleType.hasOwnProperty(reCaptchaId) ||\n                    recaptchaRegistry._isInvisibleType[reCaptchaId] === false\n                ) {\n                    //remove listener so that place order action is only triggered by the 'Place Order' button\n                    recaptchaRegistry.removeListener(reCaptchaId);\n                }\n\n                return recaptchaDeferred;\n            }\n\n            //No ReCaptcha, just sending the request\n            return originalAction(serviceUrl, payload, messageContainer);\n        });\n    };\n});\n","Magento_OfflineShipping/js/view/shipping-rates-validation/flatrate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/shipping-rates-validator',\n    'Magento_Checkout/js/model/shipping-rates-validation-rules',\n    '../../model/shipping-rates-validator/flatrate',\n    '../../model/shipping-rates-validation-rules/flatrate'\n], function (\n    Component,\n    defaultShippingRatesValidator,\n    defaultShippingRatesValidationRules,\n    flatrateShippingRatesValidator,\n    flatrateShippingRatesValidationRules\n) {\n    'use strict';\n\n    defaultShippingRatesValidator.registerValidator('flatrate', flatrateShippingRatesValidator);\n    defaultShippingRatesValidationRules.registerRules('flatrate', flatrateShippingRatesValidationRules);\n\n    return Component;\n});\n","Magento_OfflineShipping/js/view/shipping-rates-validation/freeshipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/shipping-rates-validator',\n    'Magento_Checkout/js/model/shipping-rates-validation-rules',\n    '../../model/shipping-rates-validator/freeshipping',\n    '../../model/shipping-rates-validation-rules/freeshipping'\n], function (\n    Component,\n    defaultShippingRatesValidator,\n    defaultShippingRatesValidationRules,\n    freeshippingShippingRatesValidator,\n    freeshippingShippingRatesValidationRules\n) {\n    'use strict';\n\n    defaultShippingRatesValidator.registerValidator('freeshipping', freeshippingShippingRatesValidator);\n    defaultShippingRatesValidationRules.registerRules('freeshipping', freeshippingShippingRatesValidationRules);\n\n    return Component;\n});\n","Magento_OfflineShipping/js/view/shipping-rates-validation/tablerate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/shipping-rates-validator',\n    'Magento_Checkout/js/model/shipping-rates-validation-rules',\n    '../../model/shipping-rates-validator/tablerate',\n    '../../model/shipping-rates-validation-rules/tablerate'\n], function (\n    Component,\n    defaultShippingRatesValidator,\n    defaultShippingRatesValidationRules,\n    tablerateShippingRatesValidator,\n    tablerateShippingRatesValidationRules\n) {\n    'use strict';\n\n    defaultShippingRatesValidator.registerValidator('tablerate', tablerateShippingRatesValidator);\n    defaultShippingRatesValidationRules.registerRules('tablerate', tablerateShippingRatesValidationRules);\n\n    return Component;\n});\n","Magento_OfflineShipping/js/model/shipping-rates-validation-rules/flatrate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return {\n                'country_id': {\n                    'required': true\n                }\n            };\n        }\n    };\n});\n","Magento_OfflineShipping/js/model/shipping-rates-validation-rules/freeshipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return {\n                'country_id': {\n                    'required': true\n                }\n            };\n        }\n    };\n});\n","Magento_OfflineShipping/js/model/shipping-rates-validation-rules/tablerate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return {\n                'postcode': {\n                    'required': true\n                },\n                'country_id': {\n                    'required': true\n                },\n                'region_id': {\n                    'required': true\n                },\n                'region_id_input': {\n                    'required': true\n                }\n            };\n        }\n    };\n});\n","Magento_OfflineShipping/js/model/shipping-rates-validator/flatrate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mageUtils',\n    '../shipping-rates-validation-rules/flatrate',\n    'mage/translate'\n], function ($, utils, validationRules, $t) {\n    'use strict';\n\n    return {\n        validationErrors: [],\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validate: function (address) {\n            var self = this;\n\n            this.validationErrors = [];\n            $.each(validationRules.getRules(), function (field, rule) {\n                var message;\n\n                if (rule.required && utils.isEmpty(address[field])) {\n                    message = $t('Field ') + field + $t(' is required.');\n                    self.validationErrors.push(message);\n                }\n            });\n\n            return !this.validationErrors.length;\n        }\n    };\n});\n","Magento_OfflineShipping/js/model/shipping-rates-validator/freeshipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mageUtils',\n    '../shipping-rates-validation-rules/freeshipping',\n    'mage/translate'\n], function ($, utils, validationRules, $t) {\n    'use strict';\n\n    return {\n        validationErrors: [],\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validate: function (address) {\n            var self = this;\n\n            this.validationErrors = [];\n            $.each(validationRules.getRules(), function (field, rule) {\n                var message;\n\n                if (rule.required && utils.isEmpty(address[field])) {\n                    message = $t('Field ') + field + $t(' is required.');\n                    self.validationErrors.push(message);\n                }\n            });\n\n            return !this.validationErrors.length;\n        }\n    };\n});\n","Magento_OfflineShipping/js/model/shipping-rates-validator/tablerate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mageUtils',\n    '../shipping-rates-validation-rules/tablerate',\n    'mage/translate'\n], function ($, utils, validationRules, $t) {\n    'use strict';\n\n    return {\n        validationErrors: [],\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validate: function (address) {\n            var self = this;\n\n            this.validationErrors = [];\n            $.each(validationRules.getRules(), function (field, rule) {\n                var message, regionFields;\n\n                if (rule.required && utils.isEmpty(address[field])) {\n                    message = $t('Field ') + field + $t(' is required.');\n                    regionFields = ['region', 'region_id', 'region_id_input'];\n\n                    if (\n                        $.inArray(field, regionFields) === -1 ||\n                        utils.isEmpty(address.region) && utils.isEmpty(address['region_id'])\n                    ) {\n                        self.validationErrors.push(message);\n                    }\n                }\n            });\n\n            return !this.validationErrors.length;\n        }\n    };\n});\n","Magento_Dhl/js/view/shipping-rates-validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/shipping-rates-validator',\n    'Magento_Checkout/js/model/shipping-rates-validation-rules',\n    'Magento_Dhl/js/model/shipping-rates-validator',\n    'Magento_Dhl/js/model/shipping-rates-validation-rules'\n], function (\n    Component,\n    defaultShippingRatesValidator,\n    defaultShippingRatesValidationRules,\n    dhlShippingRatesValidator,\n    dhlShippingRatesValidationRules\n) {\n    'use strict';\n\n    defaultShippingRatesValidator.registerValidator('dhl', dhlShippingRatesValidator);\n    defaultShippingRatesValidationRules.registerRules('dhl', dhlShippingRatesValidationRules);\n\n    return Component;\n});\n","Magento_Dhl/js/model/shipping-rates-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mageUtils',\n    'Magento_Dhl/js/model/shipping-rates-validation-rules',\n    'mage/translate'\n], function ($, utils, validationRules, $t) {\n    'use strict';\n\n    return {\n        validationErrors: [],\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validate: function (address) {\n            var self = this;\n\n            this.validationErrors = [];\n            $.each(validationRules.getRules(), function (field, rule) {\n                var message;\n\n                if (rule.required && utils.isEmpty(address[field])) {\n                    message = $t('Field ') + field + $t(' is required.');\n\n                    self.validationErrors.push(message);\n                }\n            });\n\n            return !this.validationErrors.length;\n        }\n    };\n});\n","Magento_Dhl/js/model/shipping-rates-validation-rules.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return {\n                'postcode': {\n                    'required': true\n                },\n                'country_id': {\n                    'required': true\n                },\n                'city': {\n                    'required': true\n                }\n            };\n        }\n    };\n});\n","Magento_Review/js/error-placement.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/mage'\n], function ($) {\n    'use strict';\n\n    return function (config, element) {\n        $(element).mage('validation', {\n            /** @inheritdoc */\n            errorPlacement: function (error, el) {\n\n                if (el.parents('#product-review-table').length) {\n                    $('#product-review-table').siblings(this.errorElement + '.' + this.errorClass).remove();\n                    $('#product-review-table').after(error);\n                } else {\n                    el.after(error);\n                }\n            }\n        });\n    };\n});\n","Magento_Review/js/validate-review.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery/validate',\n    'mage/translate'\n], function ($) {\n    'use strict';\n\n    $.validator.addMethod(\n        'rating-required', function (value) {\n            return value !== undefined;\n        }, $.mage.__('Please select one of each of the ratings above.'));\n});\n","Magento_Review/js/submit-review.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery'\n], function ($) {\n    'use strict';\n\n    return function (config, element) {\n        $(element).on('submit', function () {\n            if ($(this).valid()) {\n                $(this).find('.submit').attr('disabled', true);\n            }\n        });\n    };\n});\n","Magento_Review/js/process-reviews.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'tabs',\n    'collapsible'\n], function ($) {\n    'use strict';\n\n    /**\n     * @param {String} url\n     * @param {*} fromPages\n     */\n    function processReviews(url, fromPages) {\n        $.ajax({\n            url: url,\n            cache: true,\n            dataType: 'html',\n            showLoader: false,\n            loaderContext: $('.product.data.items')\n        }).done(function (data) {\n            $('#product-review-container').html(data).trigger('contentUpdated');\n            $('[data-role=\"product-review\"] .pages a').each(function (index, element) {\n                $(element).on('click', function (event) { //eslint-disable-line max-nested-callbacks\n                    processReviews($(element).attr('href'), true);\n                    event.preventDefault();\n                });\n            });\n        }).always(function () {\n            if (fromPages == true) { //eslint-disable-line eqeqeq\n                $('html, body').animate({\n                    scrollTop: $('#reviews').offset().top - 50\n                }, 300);\n            }\n        });\n    }\n\n    return function (config) {\n        var reviewTab = $(config.reviewsTabSelector),\n            requiredReviewTabRole = 'tab';\n\n        if (reviewTab.attr('role') === requiredReviewTabRole && reviewTab.hasClass('active')) {\n            processReviews(config.productReviewUrl, location.hash === '#reviews');\n        } else {\n            reviewTab.one('beforeOpen', function () {\n                processReviews(config.productReviewUrl);\n            });\n        }\n\n        $(function () {\n            $('.product-info-main .reviews-actions a').on('click', function (event) {\n                var anchor, addReviewBlock;\n\n                event.preventDefault();\n                anchor = $(this).attr('href').replace(/^.*?(#|$)/, '');\n                addReviewBlock = $('#' + anchor);\n\n                if (addReviewBlock.length) {\n                    $('.product.data.items [data-role=\"content\"]').each(function (index) { //eslint-disable-line\n                        if (this.id == 'reviews') { //eslint-disable-line eqeqeq\n                            $('.product.data.items').tabs('activate', index);\n                        }\n                    });\n                    $('html, body').animate({\n                        scrollTop: addReviewBlock.offset().top - 50\n                    }, 300);\n                }\n\n            });\n        });\n    };\n});\n","Magento_Review/js/view/review.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Customer/js/customer-data',\n    'Magento_Customer/js/view/customer'\n], function (Component, customerData) {\n    'use strict';\n\n    return Component.extend({\n        /** @inheritdoc */\n        initialize: function () {\n            this._super();\n\n            this.review = customerData.get('review').extend({\n                disposableCustomerData: 'review'\n            });\n        },\n\n        /**\n         * @return {*}\n         */\n        nickname: function () {\n            return this.review().nickname || customerData.get('customer')().firstname;\n        }\n    });\n});\n","Magento_Captcha/js/captcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    /**\n     * @api\n     */\n    $.widget('mage.captcha', {\n        options: {\n            refreshClass: 'refreshing',\n            reloadSelector: '.captcha-reload',\n            imageSelector: '.captcha-img',\n            imageLoader: ''\n        },\n\n        /**\n         * Method binds click event to reload image\n         * @private\n         */\n        _create: function () {\n            this.element.on('click', this.options.reloadSelector, $.proxy(this.refresh, this));\n        },\n\n        /**\n         * Method triggers an AJAX request to refresh the CAPTCHA image\n         */\n        refresh: function () {\n            var imageLoader = this.options.imageLoader;\n\n            if (imageLoader) {\n                this.element.find(this.options.imageSelector).attr('src', imageLoader);\n            }\n            this.element.addClass(this.options.refreshClass);\n\n            $.ajax({\n                url: this.options.url,\n                type: 'post',\n                dataType: 'json',\n                context: this,\n                data: {\n                    'formId': this.options.type\n                },\n\n                /**\n                 * @param {Object} response\n                 */\n                success: function (response) {\n                    if (response.imgSrc) {\n                        this.element.find(this.options.imageSelector).attr('src', response.imgSrc);\n                    }\n                },\n\n                /** Complete callback. */\n                complete: function () {\n                    this.element.removeClass(this.options.refreshClass);\n                }\n            });\n        }\n    });\n\n    return $.mage.captcha;\n});\n","Magento_Captcha/js/action/refresh.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery', 'mage/url'\n], function ($, urlBuilder) {\n    'use strict';\n\n    return function (refreshUrl, formId, imageSource) {\n        return $.ajax({\n            url: urlBuilder.build(refreshUrl),\n            type: 'POST',\n            data: JSON.stringify({\n                'formId': formId\n            }),\n            global: false,\n            contentType: 'application/json'\n        }).done(\n            function (response) {\n                if (response.imgSrc) {\n                    imageSource(response.imgSrc);\n                }\n            }\n        );\n    };\n});\n","Magento_Captcha/js/view/checkout/loginCaptcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'Magento_Captcha/js/view/checkout/defaultCaptcha',\n    'Magento_Captcha/js/model/captchaList',\n    'Magento_Customer/js/action/login',\n    'underscore'\n],\nfunction (defaultCaptcha, captchaList, loginAction, _) {\n    'use strict';\n\n    return defaultCaptcha.extend({\n        /** @inheritdoc */\n        initialize: function () {\n            var self = this,\n                currentCaptcha;\n\n            this._super();\n            currentCaptcha = captchaList.getCaptchaByFormId(this.formId);\n\n            if (currentCaptcha != null) {\n                currentCaptcha.setIsVisible(true);\n                this.setCurrentCaptcha(currentCaptcha);\n\n                loginAction.registerLoginCallback(function (loginData) {\n                    if (loginData['captcha_form_id'] &&\n                        loginData['captcha_form_id'] === self.formId &&\n                        self.isRequired()\n                    ) {\n                        _.defer(self.refresh.bind(self));\n                    }\n                });\n            }\n        }\n    });\n});\n","Magento_Captcha/js/view/checkout/defaultCaptcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'uiComponent',\n    'Magento_Captcha/js/model/captcha',\n    'Magento_Captcha/js/model/captchaList',\n    'Magento_Customer/js/customer-data',\n    'underscore'\n], function ($, Component, Captcha, captchaList, customerData, _) {\n    'use strict';\n\n    var captchaConfig;\n\n    return Component.extend({\n        defaults: {\n            template: 'Magento_Captcha/checkout/captcha'\n        },\n        dataScope: 'global',\n        currentCaptcha: null,\n        subscribedFormIds: [],\n\n        /**\n         * @return {*}\n         */\n        captchaValue: function () {\n            return this.currentCaptcha.getCaptchaValue();\n        },\n\n        /** @inheritdoc */\n        initialize: function () {\n            this._super();\n\n            if (window[this.configSource] && window[this.configSource].captcha) {\n                captchaConfig = window[this.configSource].captcha;\n                $.each(captchaConfig, function (formId, captchaData) {\n                    var captcha;\n\n                    captchaData.formId = formId;\n                    captcha = Captcha(captchaData);\n                    this.checkCustomerData(formId, customerData.get('captcha')(), captcha);\n                    this.subscribeCustomerData(formId, captcha);\n                    captchaList.add(captcha);\n                }.bind(this));\n            }\n        },\n\n        /**\n         * Check customer data for captcha configuration.\n         *\n         * @param {String} formId\n         * @param {Object} captchaData\n         * @param {Object} captcha\n         */\n        checkCustomerData: function (formId, captchaData, captcha) {\n            if (!_.isEmpty(captchaData) &&\n                !_.isEmpty(captchaData[formId]) &&\n                captchaData[formId].timestamp > captcha.timestamp\n            ) {\n                if (!captcha.isRequired() && captchaData[formId].isRequired) {\n                    captcha.refresh();\n                }\n                captcha.isRequired(captchaData[formId].isRequired);\n                captcha.timestamp = captchaData[formId].timestamp;\n            }\n        },\n\n        /**\n         * Subscribe for customer data updates.\n         *\n         * @param {String} formId\n         * @param {Object} captcha\n         */\n        subscribeCustomerData: function (formId, captcha) {\n            if (this.subscribedFormIds.includes(formId) === false) {\n                this.subscribedFormIds.push(formId);\n                customerData.get('captcha').subscribe(function (captchaData) {\n                    this.checkCustomerData(formId, captchaData, captcha);\n                }.bind(this));\n            }\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        getIsLoading: function () {\n            return this.currentCaptcha !== null ? this.currentCaptcha.isLoading : false;\n        },\n\n        /**\n         * @return {null|Object}\n         */\n        getCurrentCaptcha: function () {\n            return this.currentCaptcha;\n        },\n\n        /**\n         * @param {Object} captcha\n         */\n        setCurrentCaptcha: function (captcha) {\n            this.currentCaptcha = captcha;\n        },\n\n        /**\n         * @return {String|null}\n         */\n        getFormId: function () {\n            return this.currentCaptcha !== null ? this.currentCaptcha.getFormId() : null;\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        getIsVisible: function () {\n            return this.currentCaptcha !== null ? this.currentCaptcha.getIsVisible() : false;\n        },\n\n        /**\n         * @param {Boolean} flag\n         */\n        setIsVisible: function (flag) {\n            this.currentCaptcha.setIsVisible(flag);\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isRequired: function () {\n            return this.currentCaptcha !== null ? this.currentCaptcha.getIsRequired() : false;\n        },\n\n        /**\n         * Set isRequired on current captcha model.\n         *\n         * @param {Boolean} flag\n         */\n        setIsRequired: function (flag) {\n            this.currentCaptcha.setIsRequired(flag);\n        },\n\n        /**\n         * @return {Boolean}\n         */\n        isCaseSensitive: function () {\n            return this.currentCaptcha !== null ? this.currentCaptcha.getIsCaseSensitive() : false;\n        },\n\n        /**\n         * @return {String|Number|null}\n         */\n        imageHeight: function () {\n            return this.currentCaptcha !== null ? this.currentCaptcha.getImageHeight() : null;\n        },\n\n        /**\n         * @return {String|null}\n         */\n        getImageSource: function () {\n            return this.currentCaptcha !== null ? this.currentCaptcha.getImageSource() : null;\n        },\n\n        /**\n         * Refresh captcha.\n         */\n        refresh: function () {\n            this.currentCaptcha.refresh();\n        }\n    });\n});\n","Magento_Captcha/js/model/captcha.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'ko',\n    'Magento_Captcha/js/action/refresh'\n], function ($, ko, refreshAction) {\n    'use strict';\n\n    return function (captchaData) {\n        return {\n            formId: captchaData.formId,\n            imageSource: ko.observable(captchaData.imageSrc),\n            visibility: ko.observable(false),\n            captchaValue: ko.observable(null),\n            isRequired: ko.observable(captchaData.isRequired),\n            isCaseSensitive: captchaData.isCaseSensitive,\n            imageHeight: captchaData.imageHeight,\n            refreshUrl: captchaData.refreshUrl,\n            isLoading: ko.observable(false),\n            timestamp: null,\n\n            /**\n             * @return {String}\n             */\n            getFormId: function () {\n                return this.formId;\n            },\n\n            /**\n             * @param {String} formId\n             */\n            setFormId: function (formId) {\n                this.formId = formId;\n            },\n\n            /**\n             * @return {Boolean}\n             */\n            getIsVisible: function () {\n                return this.visibility();\n            },\n\n            /**\n             * @param {Boolean} flag\n             */\n            setIsVisible: function (flag) {\n                this.visibility(flag);\n            },\n\n            /**\n             * @return {Boolean}\n             */\n            getIsRequired: function () {\n                return this.isRequired();\n            },\n\n            /**\n             * @param {Boolean} flag\n             */\n            setIsRequired: function (flag) {\n                this.isRequired(flag);\n            },\n\n            /**\n             * @return {Boolean}\n             */\n            getIsCaseSensitive: function () {\n                return this.isCaseSensitive;\n            },\n\n            /**\n             * @param {Boolean} flag\n             */\n            setIsCaseSensitive: function (flag) {\n                this.isCaseSensitive = flag;\n            },\n\n            /**\n             * @return {String|Number}\n             */\n            getImageHeight: function () {\n                return this.imageHeight;\n            },\n\n            /**\n             * @param {String|Number}height\n             */\n            setImageHeight: function (height) {\n                this.imageHeight = height;\n            },\n\n            /**\n             * @return {String}\n             */\n            getImageSource: function () {\n                return this.imageSource;\n            },\n\n            /**\n             * @param {String} imageSource\n             */\n            setImageSource: function (imageSource) {\n                this.imageSource(imageSource);\n            },\n\n            /**\n             * @return {String}\n             */\n            getRefreshUrl: function () {\n                return this.refreshUrl;\n            },\n\n            /**\n             * @param {String} url\n             */\n            setRefreshUrl: function (url) {\n                this.refreshUrl = url;\n            },\n\n            /**\n             * @return {*}\n             */\n            getCaptchaValue: function () {\n                return this.captchaValue;\n            },\n\n            /**\n             * @param {*} value\n             */\n            setCaptchaValue: function (value) {\n                this.captchaValue(value);\n            },\n\n            /**\n             * Refresh captcha.\n             */\n            refresh: function () {\n                var refresh,\n                    self = this;\n\n                this.isLoading(true);\n\n                refresh = refreshAction(this.getRefreshUrl(), this.getFormId(), this.getImageSource());\n                $.when(refresh).done(function () {\n                    self.isLoading(false);\n                });\n            }\n        };\n    };\n});\n","Magento_Captcha/js/model/captchaList.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['jquery'], function ($) {\n    'use strict';\n\n    var captchaList = [];\n\n    return {\n        /**\n         * @param {Object} captcha\n         */\n        add: function (captcha) {\n            captchaList.push(captcha);\n        },\n\n        /**\n         * @param {String} formId\n         * @return {Object}\n         */\n        getCaptchaByFormId: function (formId) {\n            var captcha = null;\n\n            $.each(captchaList, function (key, item) {\n                if (formId === item.formId) {\n                    captcha = item;\n\n                    return false;\n                }\n            });\n\n            return captcha;\n        },\n\n        /**\n         * @return {Array}\n         */\n        getCaptchaList: function () {\n            return captchaList;\n        }\n    };\n});\n","Magento_Usps/js/view/shipping-rates-validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/shipping-rates-validator',\n    'Magento_Checkout/js/model/shipping-rates-validation-rules',\n    '../model/shipping-rates-validator',\n    '../model/shipping-rates-validation-rules'\n], function (\n    Component,\n    defaultShippingRatesValidator,\n    defaultShippingRatesValidationRules,\n    uspsShippingRatesValidator,\n    uspsShippingRatesValidationRules\n) {\n    'use strict';\n\n    defaultShippingRatesValidator.registerValidator('usps', uspsShippingRatesValidator);\n    defaultShippingRatesValidationRules.registerRules('usps', uspsShippingRatesValidationRules);\n\n    return Component;\n});\n","Magento_Usps/js/model/shipping-rates-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mageUtils',\n    './shipping-rates-validation-rules',\n    'mage/translate'\n], function ($, utils, validationRules, $t) {\n    'use strict';\n\n    var checkoutConfig = window.checkoutConfig;\n\n    return {\n        validationErrors: [],\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validate: function (address) {\n            var rules = validationRules.getRules(),\n                self = this;\n\n            $.each(rules, function (field, rule) {\n                var message;\n\n                if (rule.required && utils.isEmpty(address[field])) {\n                    message = $t('Field ') + field + $t(' is required.');\n                    self.validationErrors.push(message);\n                }\n            });\n\n            if (!this.validationErrors.length) {\n                if (address['country_id'] == checkoutConfig.originCountryCode) { //eslint-disable-line eqeqeq\n                    return !utils.isEmpty(address.postcode);\n                }\n\n                return true;\n            }\n\n            return false;\n        }\n    };\n});\n","Magento_Usps/js/model/shipping-rates-validation-rules.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return {\n                'country_id': {\n                    'required': true\n                },\n                'postcode': {\n                    'required': false\n                }\n            };\n        }\n    };\n});\n","Magento_PageCache/js/form-key-provider.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(function () {\n    'use strict';\n\n    return function (settings) {\n        var formKey,\n            inputElements,\n            inputSelector = 'input[name=\"form_key\"]';\n\n        /**\n         * Set form_key cookie\n         * @private\n         */\n        function setFormKeyCookie(value) {\n            var expires,\n                secure,\n                date = new Date(),\n                cookiesConfig = window.cookiesConfig || {},\n                isSecure = !!cookiesConfig.secure,\n                samesite = cookiesConfig.samesite || 'lax';\n\n            date.setTime(date.getTime() + 86400000);\n            expires = '; expires=' + date.toUTCString();\n            secure = isSecure ? '; secure' : '';\n            samesite = '; samesite=' + samesite;\n\n            document.cookie = 'form_key=' + (value || '') + expires + secure + '; path=/' + samesite;\n        }\n\n        /**\n         * Retrieves form key from cookie\n         * @private\n         */\n        function getFormKeyCookie() {\n            var cookie,\n                i,\n                nameEQ = 'form_key=',\n                cookieArr = document.cookie.split(';');\n\n            for (i = 0; i < cookieArr.length; i++) {\n                cookie = cookieArr[i];\n\n                while (cookie.charAt(0) === ' ') {\n                    cookie = cookie.substring(1, cookie.length);\n                }\n\n                if (cookie.indexOf(nameEQ) === 0) {\n                    return cookie.substring(nameEQ.length, cookie.length);\n                }\n            }\n\n            return null;\n        }\n\n        /**\n         * Get form key from UI input hidden\n         * @private\n         */\n        function getFormKeyFromUI() {\n            return document.querySelector(inputSelector).value;\n        }\n\n        /**\n         * Generate form key string\n         * @private\n         */\n        function generateFormKeyString() {\n            var result = '',\n                length = 16,\n                chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\n            while (length--) {\n                result += chars[Math.round(Math.random() * (chars.length - 1))];\n            }\n\n            return result;\n        }\n\n        /**\n         * Init form_key inputs with value\n         * @private\n         */\n        function initFormKey() {\n            formKey = getFormKeyCookie();\n\n            if (settings && settings.isPaginationCacheEnabled && !formKey) {\n                formKey = getFormKeyFromUI();\n                setFormKeyCookie(formKey);\n            }\n\n            if (!formKey) {\n                formKey = generateFormKeyString();\n                setFormKeyCookie(formKey);\n            }\n            inputElements = document.querySelectorAll(inputSelector);\n\n            if (inputElements.length) {\n                Array.prototype.forEach.call(inputElements, function (element) {\n                    element.setAttribute('value', formKey);\n                });\n            }\n        }\n\n        initFormKey();\n    };\n});\n","Magento_PageCache/js/page-cache.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'domReady',\n    'consoleLogger',\n    'Magento_PageCache/js/form-key-provider',\n    'jquery-ui-modules/widget',\n    'mage/cookies'\n], function ($, domReady, consoleLogger, formKeyInit) {\n    'use strict';\n\n    /**\n     * Helper. Generate random string\n     * TODO: Merge with mage/utils\n     * @param {String} chars - list of symbols\n     * @param {Number} length - length for need string\n     * @returns {String}\n     */\n    function generateRandomString(chars, length) {\n        var result = '';\n\n        length = length > 0 ? length : 1;\n\n        while (length--) {\n            result += chars[Math.round(Math.random() * (chars.length - 1))];\n        }\n\n        return result;\n    }\n\n    /**\n     * Nodes tree to flat list converter\n     * @returns {Array}\n     */\n    $.fn.comments = function () {\n        var elements = [],\n            contents,\n            elementContents;\n\n        /**\n         * @param {jQuery} element - Comment holder\n         */\n        (function lookup(element) {\n            var iframeHostName;\n\n            // prevent cross origin iframe content reading\n            if ($(element).prop('tagName') === 'IFRAME') {\n                iframeHostName = $('<a>').prop('href', $(element).prop('src'))\n                    .prop('hostname');\n\n                if (window.location.hostname !== iframeHostName) {\n                    return [];\n                }\n            }\n\n            /**\n             * Rewrite jQuery contents().\n             *\n             * @param {jQuery} elem\n             */\n            contents = function (elem) {\n                return $.map(elem, function (el) {\n                    try {\n                        return el.nodeName.toLowerCase() === 'iframe' ?\n                            el.contentDocument || (el.contentWindow ? el.contentWindow.document : []) :\n                            $.merge([], el.childNodes);\n                    } catch (e) {\n                        consoleLogger.error(e);\n\n                        return [];\n                    }\n                });\n            };\n\n            elementContents = contents($(element));\n\n            $.each(elementContents, function (index, el) {\n                switch (el.nodeType) {\n                    case 1: // ELEMENT_NODE\n                        lookup(el);\n                        break;\n\n                    case 8: // COMMENT_NODE\n                        elements.push(el);\n                        break;\n\n                    case 9: // DOCUMENT_NODE\n                        lookup($(el).find('body'));\n                        break;\n                }\n            });\n        })(this);\n\n        return elements;\n    };\n\n    /**\n     * FormKey Widget - this widget is generating from key, saves it to cookie and\n     * @deprecated see Magento/PageCache/view/frontend/web/js/form-key-provider.js\n     */\n    $.widget('mage.formKey', {\n        options: {\n            inputSelector: 'input[name=\"form_key\"]',\n            allowedCharacters: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',\n            length: 16\n        },\n\n        /**\n         * Creates widget 'mage.formKey'\n         * @private\n         */\n        _create: function () {\n            var formKey = $.mage.cookies.get('form_key'),\n                options = {\n                    secure: window.cookiesConfig ? window.cookiesConfig.secure : false\n                };\n\n            if (!formKey) {\n                formKey = generateRandomString(this.options.allowedCharacters, this.options.length);\n                $.mage.cookies.set('form_key', formKey, options);\n            }\n            $(this.options.inputSelector).val(formKey);\n        }\n    });\n\n    /**\n     * PageCache Widget\n     * Handles additional ajax request for rendering user private content.\n     */\n    $.widget('mage.pageCache', {\n        options: {\n            url: '/',\n            patternPlaceholderOpen: /^ BLOCK (.+) $/,\n            patternPlaceholderClose: /^ \\/BLOCK (.+) $/,\n            versionCookieName: 'private_content_version',\n            handles: []\n        },\n\n        /**\n         * Creates widget 'mage.pageCache'\n         * @private\n         */\n        _create: function () {\n            var placeholders,\n                version = $.mage.cookies.get(this.options.versionCookieName);\n\n            if (!version) {\n                return;\n            }\n            placeholders = this._searchPlaceholders(this.element.comments());\n\n            if (placeholders && placeholders.length) {\n                this._ajax(placeholders, version);\n            }\n        },\n\n        /**\n         * Parse page for placeholders.\n         * @param {Array} elements\n         * @returns {Array}\n         * @private\n         */\n        _searchPlaceholders: function (elements) {\n            var placeholders = [],\n                tmp = {},\n                ii,\n                len,\n                el, matches, name;\n\n            if (!(elements && elements.length)) {\n                return placeholders;\n            }\n\n            for (ii = 0, len = elements.length; ii < len; ii++) {\n                el = elements[ii];\n                matches = this.options.patternPlaceholderOpen.exec(el.nodeValue);\n                name = null;\n\n                if (matches) {\n                    name = matches[1];\n                    tmp[name] = {\n                        name: name,\n                        openElement: el\n                    };\n                } else {\n                    matches = this.options.patternPlaceholderClose.exec(el.nodeValue);\n\n                    if (matches) { //eslint-disable-line max-depth\n                        name = matches[1];\n\n                        if (tmp[name]) { //eslint-disable-line max-depth\n                            tmp[name].closeElement = el;\n                            placeholders.push(tmp[name]);\n                            delete tmp[name];\n                        }\n                    }\n                }\n            }\n\n            return placeholders;\n        },\n\n        /**\n         * Parse for page and replace placeholders\n         * @param {Object} placeholder\n         * @param {Object} html\n         * @protected\n         */\n        _replacePlaceholder: function (placeholder, html) {\n            var startReplacing = false,\n                prevSibling = null,\n                parent, contents, yy, len, element;\n\n            if (!placeholder || !html) {\n                return;\n            }\n\n            parent = $(placeholder.openElement).parent();\n            contents = parent.contents();\n\n            for (yy = 0, len = contents.length; yy < len; yy++) {\n                element = contents[yy];\n\n                if (element == placeholder.openElement) { //eslint-disable-line eqeqeq\n                    startReplacing = true;\n                }\n\n                if (startReplacing) {\n                    $(element).remove();\n                } else if (element.nodeType != 8) { //eslint-disable-line eqeqeq\n                    //due to comment tag doesn't have siblings we try to find it manually\n                    prevSibling = element;\n                }\n\n                if (element == placeholder.closeElement) { //eslint-disable-line eqeqeq\n                    break;\n                }\n            }\n\n            if (prevSibling) {\n                $(prevSibling).after(html);\n            } else {\n                $(parent).prepend(html);\n            }\n\n            // trigger event to use mage-data-init attribute\n            $(parent).trigger('contentUpdated');\n        },\n\n        /**\n         * AJAX helper\n         * @param {Object} placeholders\n         * @param {String} version\n         * @private\n         */\n        _ajax: function (placeholders, version) {\n            var ii,\n                data = {\n                    blocks: [],\n                    handles: this.options.handles,\n                    originalRequest: this.options.originalRequest,\n                    version: version\n                };\n\n            for (ii = 0; ii < placeholders.length; ii++) {\n                data.blocks.push(placeholders[ii].name);\n            }\n            data.blocks = JSON.stringify(data.blocks.sort());\n            data.handles = JSON.stringify(data.handles);\n            data.originalRequest = JSON.stringify(data.originalRequest);\n            $.ajax({\n                url: this.options.url,\n                data: data,\n                type: 'GET',\n                cache: true,\n                dataType: 'json',\n                context: this,\n\n                /**\n                 * Response handler\n                 * @param {Object} response\n                 */\n                success: function (response) {\n                    var placeholder, i;\n\n                    for (i = 0; i < placeholders.length; i++) {\n                        placeholder = placeholders[i];\n\n                        if (response.hasOwnProperty(placeholder.name)) {\n                            this._replacePlaceholder(placeholder, response[placeholder.name]);\n                        }\n                    }\n                }\n            });\n        }\n    });\n\n    domReady(function () {\n        formKeyInit();\n    });\n\n    return {\n        'pageCache': $.mage.pageCache,\n        'formKey': $.mage.formKey\n    };\n});\n","mage/multiselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery',\n    'text!mage/multiselect.html',\n    'Magento_Ui/js/modal/alert',\n    'jquery-ui-modules/widget',\n    'jquery/editableMultiselect/js/jquery.multiselect'\n], function (_, $, searchTemplate, alert) {\n    'use strict';\n\n    $.widget('mage.multiselect2', {\n        options: {\n            mselectContainer: 'section.mselect-list',\n            mselectItemsWrapperClass: 'mselect-items-wrapper',\n            mselectCheckedClass: 'mselect-checked',\n            containerClass: 'paginated',\n            searchInputClass: 'admin__action-multiselect-search',\n            selectedItemsCountClass: 'admin__action-multiselect-items-selected',\n            currentPage: 1,\n            lastAppendValue: 0,\n            updateDelay: 1000,\n            optionsLoaded: false\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            $.fn.multiselect.call(this.element, this.options);\n        },\n\n        /** @inheritdoc */\n        _init: function () {\n            this.domElement = this.element.get(0);\n\n            this.$container = $(this.options.mselectContainer);\n            this.$wrapper = this.$container.find('.' + this.options.mselectItemsWrapperClass);\n            this.$item = this.$wrapper.find('div').first();\n            this.selectedValues = [];\n            this.values = {};\n\n            this.$container.addClass(this.options.containerClass).prepend(searchTemplate);\n            this.$input = this.$container.find('.' + this.options.searchInputClass);\n            this.$selectedCounter = this.$container.find('.' + this.options.selectedItemsCountClass);\n            this.filter = '';\n\n            if (this.domElement.options.length) {\n                this._setLastAppendOption(this.domElement.options[this.domElement.options.length - 1].value);\n            }\n\n            this._initElement();\n            this._events();\n        },\n\n        /**\n         * Leave only saved/selected options in select element.\n         *\n         * @private\n         */\n        _initElement: function () {\n            this.element.empty();\n            _.each(this.options.selectedValues, function (value) {\n                this._createSelectedOption({\n                    value: value,\n                    label: value\n                });\n            }, this);\n        },\n\n        /**\n         * Attach required events.\n         *\n         * @private\n         */\n        _events: function () {\n            var onKeyUp = _.debounce(this.onKeyUp, this.options.updateDelay);\n\n            _.bindAll(this, 'onScroll', 'onCheck', 'onOptionsChange');\n\n            this.$wrapper.on('scroll', this.onScroll);\n            this.$wrapper.on('change.mselectCheck', '[type=checkbox]', this.onCheck);\n            this.$input.on('keyup', _.bind(onKeyUp, this));\n            this.element.on('change.hiddenSelect', this.onOptionsChange);\n        },\n\n        /**\n         * Behaves multiselect scroll.\n         */\n        onScroll: function () {\n            var height = this.$wrapper.height(),\n                scrollHeight = this.$wrapper.prop('scrollHeight'),\n                scrollTop = Math.ceil(this.$wrapper.prop('scrollTop'));\n\n            if (!this.options.optionsLoaded && scrollHeight - height <= scrollTop) {\n                this.loadOptions();\n            }\n        },\n\n        /**\n         * Behaves keyup event on input search\n         */\n        onKeyUp: function () {\n            if (this.getSearchCriteria() === this.filter) {\n                return false;\n            }\n\n            this.setFilter();\n            this.clearMultiselectOptions();\n            this.setCurrentPage(0);\n            this.loadOptions();\n        },\n\n        /**\n         * Callback for select change event\n         */\n        onOptionsChange: function () {\n            this.selectedValues = _.map(this.domElement.options, function (option) {\n                this.values[option.value] = true;\n\n                return option.value;\n            }, this);\n\n            this._updateSelectedCounter();\n        },\n\n        /**\n         * Overrides native check behaviour.\n         *\n         * @param {Event} event\n         */\n        onCheck: function (event) {\n            var checkbox = event.target,\n                option = {\n                    value: checkbox.value,\n                    label: $(checkbox).parent('label').text()\n                };\n\n            checkbox.checked ? this._createSelectedOption(option) : this._removeSelectedOption(option);\n            event.stopPropagation();\n        },\n\n        /**\n         * Show error message.\n         *\n         * @param {String} message\n         */\n        onError: function (message) {\n            alert({\n                content: message\n            });\n        },\n\n        /**\n         * Updates current filter state.\n         */\n        setFilter: function () {\n            this.filter = this.getSearchCriteria() || '';\n        },\n\n        /**\n         * Reads search input value.\n         *\n         * @return {String}\n         */\n        getSearchCriteria: function () {\n            return this.$input.val().trim();\n        },\n\n        /**\n         * Load options data.\n         */\n        loadOptions: function () {\n            var nextPage = this.getCurrentPage() + 1;\n\n            this.$wrapper.trigger('processStart');\n            this.$input.prop('disabled', true);\n\n            $.get(this.options.nextPageUrl, {\n                p: nextPage,\n                s: this.filter\n            })\n            .done(function (response) {\n                if (response.success) {\n                    this.appendOptions(response.result);\n                    this.setCurrentPage(nextPage);\n                } else {\n                    this.onError(response.errorMessage);\n                }\n            }.bind(this))\n            .always(function () {\n                this.$wrapper.trigger('processStop');\n                this.$input.prop('disabled', false);\n\n                if (this.filter) {\n                    this.$input.focus();\n                }\n            }.bind(this));\n        },\n\n        /**\n         * Append loaded options\n         *\n         * @param {Array} options\n         */\n        appendOptions: function (options) {\n            var divOptions = [];\n\n            if (!options.length) {\n                return false;\n            }\n\n            if (this.isOptionsLoaded(options)) {\n                return;\n            }\n\n            options.forEach(function (option) {\n                if (!this.values[option.value]) {\n                    this.values[option.value] = true;\n                    option.selected = this._isOptionSelected(option);\n                    divOptions.push(this._createMultiSelectOption(option));\n                    this._setLastAppendOption(option.value);\n                }\n            }, this);\n\n            this.$wrapper.append(divOptions);\n        },\n\n        /**\n         * Clear multiselect options\n         */\n        clearMultiselectOptions: function () {\n            this._setLastAppendOption(0);\n            this.values = {};\n            this.$wrapper.empty();\n        },\n\n        /**\n         * Checks if all options are already loaded\n         *\n         * @return {Boolean}\n         */\n        isOptionsLoaded: function (options) {\n            this.options.optionsLoaded = this.options.lastAppendValue === options[options.length - 1].value;\n\n            return this.options.optionsLoaded;\n        },\n\n        /**\n         * Setter for current page.\n         *\n         * @param {Number} page\n         */\n        setCurrentPage: function (page) {\n            this.options.currentPage = page;\n        },\n\n        /**\n         * Getter for current page.\n         *\n         * @return {Number}\n         */\n        getCurrentPage: function () {\n            return this.options.currentPage;\n        },\n\n        /**\n         * Creates new selected option for select element\n         *\n         * @param {Object} option - option object\n         * @param {String} option.value - option value\n         * @param {String} option.label - option label\n         * @private\n         */\n        _createSelectedOption: function (option) {\n            var selectOption = new Option(option.label, option.value, false, true);\n\n            this.element.append(selectOption);\n            this.selectedValues.push(option.value);\n            this._updateSelectedCounter();\n\n            return selectOption;\n        },\n\n        /**\n         * Remove passed option from select element\n         *\n         * @param {Object} option - option object\n         * @param {String} option.value - option value\n         * @param {String} option.label - option label\n         * @return {Object} option\n         * @private\n         */\n        _removeSelectedOption: function (option) {\n            var unselectedOption = _.findWhere(this.domElement.options, {\n                value: option.value\n            });\n\n            if (!_.isUndefined(unselectedOption)) {\n                this.domElement.remove(unselectedOption.index);\n                this.selectedValues.splice(_.indexOf(this.selectedValues, option.value), 1);\n                this._updateSelectedCounter();\n            }\n\n            return unselectedOption;\n        },\n\n        /**\n         * Creates new DIV option for multiselect widget\n         *\n         * @param {Object} option - option object\n         * @param {String} option.value - option value\n         * @param {String} option.label - option label\n         * @param {Boolean} option.selected - is option selected\n         * @private\n         */\n        _createMultiSelectOption: function (option) {\n            var item = this.$item.clone(),\n                checkbox = item.find('input'),\n                isSelected = !!option.selected;\n\n            checkbox.val(option.value)\n                .prop('checked', isSelected)\n                .toggleClass(this.options.mselectCheckedClass, isSelected);\n\n            item.find('label > span').text(option.label);\n\n            return item;\n        },\n\n        /**\n         * Checks if passed option should be selected\n         *\n         * @param {Object} option - option object\n         * @param {String} option.value - option value\n         * @param {String} option.label - option label\n         * @param {Boolean} option.selected - is option selected\n         * @return {Boolean}\n         * @private\n         */\n        _isOptionSelected: function (option) {\n            return !!~this.selectedValues.indexOf(option.value);\n        },\n\n        /**\n         * Saves last added option value.\n         *\n         * @param {Number} value\n         * @private\n         */\n        _setLastAppendOption: function (value) {\n            this.options.lastAppendValue = value;\n        },\n\n        /**\n         * Updates counter of selected items.\n         *\n         * @private\n         */\n        _updateSelectedCounter: function () {\n            this.$selectedCounter.text(this.selectedValues.length);\n        }\n    });\n\n    return $.mage.multiselect2;\n});\n","mage/tabs.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget',\n    'jquery/ui-modules/widgets/tabs',\n    'mage/mage',\n    'mage/collapsible'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.tabs', {\n        options: {\n            active: 0,\n            disabled: [],\n            openOnFocus: true,\n            collapsible: false,\n            collapsibleElement: '[data-role=collapsible]',\n            header: '[data-role=title]',\n            content: '[data-role=content]',\n            trigger: '[data-role=trigger]',\n            closedState: null,\n            openedState: null,\n            disabledState: null,\n            ajaxUrlElement: '[data-ajax=true]',\n            ajaxContent: false,\n            loadingClass: null,\n            saveState: false,\n            animate: false,\n            icons: {\n                activeHeader: null,\n                header: null\n            }\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            if (typeof this.options.disabled === 'string') {\n                this.options.disabled = this.options.disabled.split(' ').map(function (item) {\n                    return parseInt(item, 10);\n                });\n            }\n            this._processPanels();\n            this._handleDeepLinking();\n            this._processTabIndex();\n            this._closeOthers();\n            this._bind();\n        },\n\n        /**\n         * @private\n         */\n        _destroy: function () {\n            $.each(this.collapsibles, function () {\n                $(this).collapsible('destroy');\n            });\n        },\n\n        /**\n         * If deep linking is used, all sections must be closed but the one that contains the anchor.\n         * @private\n         */\n        _handleDeepLinking: function () {\n            var self = this,\n                anchor = window.location.hash,\n                isValid = $.mage.isValidSelector(anchor),\n                anchorId = anchor.replace('#', '');\n\n            if (anchor && isValid) {\n                $.each(self.contents, function (i) {\n                    if ($(this).attr('id') === anchorId || $(this).find('#' + anchorId).length) {\n                        self.collapsibles.not(self.collapsibles.eq(i)).collapsible('forceDeactivate');\n\n                        return false;\n                    }\n                });\n            }\n        },\n\n        /**\n         * When the widget gets instantiated, the first tab that is not disabled receive focusable property\n         * All tabs receive tabIndex 0\n         * @private\n         */\n        _processTabIndex: function () {\n            var self = this;\n\n            self.triggers.attr('tabIndex', 0);\n            $.each(this.collapsibles, function (i) {\n                self.triggers.attr('tabIndex', 0);\n                self.triggers.eq(i).attr('tabIndex', 0);\n            });\n        },\n\n        /**\n         * Prepare the elements for instantiating the collapsible widget\n         * @private\n         */\n        _processPanels: function () {\n            var isNotNested = this._isNotNested.bind(this);\n\n            this.contents = this.element\n                .find(this.options.content)\n                .filter(isNotNested);\n\n            this.collapsibles =  this.element\n                .find(this.options.collapsibleElement)\n                .filter(isNotNested);\n\n            this.collapsibles\n                .attr('role', 'presentation')\n                .parent()\n                .attr('role', 'tablist');\n\n            this.headers = this.element\n                .find(this.options.header)\n                .filter(isNotNested);\n\n            if (this.headers.length === 0) {\n                this.headers = this.collapsibles;\n            }\n            this.triggers = this.element\n                .find(this.options.trigger)\n                .filter(isNotNested);\n\n            if (this.triggers.length === 0) {\n                this.triggers = this.headers;\n            }\n            this._callCollapsible();\n        },\n\n        /**\n         * Checks if element is not in nested container to keep the correct scope of collapsible\n         * @param {Number} index\n         * @param {HTMLElement} element\n         * @private\n         * @return {Boolean}\n         */\n        _isNotNested: function (index, element) {\n            var parentContent = $(element).parents(this.options.content);\n\n            return !parentContent.length || !this.element.find(parentContent).length;\n        },\n\n        /**\n         * Setting the disabled and active tabs and calling instantiation of collapsible\n         * @private\n         */\n        _callCollapsible: function () {\n            var self = this,\n                disabled = false,\n                active = false;\n\n            $.each(this.collapsibles, function (i) {\n                disabled = active = false;\n\n                if ($.inArray(i, self.options.disabled) !== -1) {\n                    disabled = true;\n                }\n\n                if (i === self.options.active) {\n                    active = true;\n                }\n                self._instantiateCollapsible(this, i, active, disabled);\n            });\n        },\n\n        /**\n         * Instantiate collapsible.\n         *\n         * @param {HTMLElement} element\n         * @param {Number} index\n         * @param {*} active\n         * @param {*} disabled\n         * @private\n         */\n        _instantiateCollapsible: function (element, index, active, disabled) {\n            $(element).collapsible(\n                $.extend({}, this.options, {\n                    active: active,\n                    disabled: disabled,\n                    header: this.headers.eq(index),\n                    content: this.contents.eq(index),\n                    trigger: this.triggers.eq(index)\n                })\n            );\n        },\n\n        /**\n         * Adding callback to close others tabs when one gets opened\n         * @private\n         */\n        _closeOthers: function () {\n            var self = this;\n\n            $.each(this.collapsibles, function () {\n                $(this).on('beforeOpen', function () {\n                    self.collapsibles.not(this).collapsible('forceDeactivate');\n                });\n            });\n        },\n\n        /**\n         * @param {*} index\n         */\n        activate: function (index) {\n            this._toggleActivate('activate', index);\n        },\n\n        /**\n         * @param {*} index\n         */\n        deactivate: function (index) {\n            this._toggleActivate('deactivate', index);\n        },\n\n        /**\n         * @param {*} action\n         * @param {*} index\n         * @private\n         */\n        _toggleActivate: function (action, index) {\n            this.collapsibles.eq(index).collapsible(action);\n        },\n\n        /**\n         * @param {*} index\n         */\n        disable: function (index) {\n            this._toggleEnable('disable', index);\n        },\n\n        /**\n         * @param {*} index\n         */\n        enable: function (index) {\n            this._toggleEnable('enable', index);\n        },\n\n        /**\n         * @param {*} action\n         * @param {*} index\n         * @private\n         */\n        _toggleEnable: function (action, index) {\n            var self = this;\n\n            if (Array.isArray(index)) {\n                $.each(index, function () {\n                    self.collapsibles.eq(this).collapsible(action);\n                });\n            } else if (index === undefined) {\n                this.collapsibles.collapsible(action);\n            } else {\n                this.collapsibles.eq(index).collapsible(action);\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _keydown: function (event) {\n            var self = this,\n                keyCode, toFocus, toFocusIndex, enabledTriggers, length, currentIndex, nextToFocus;\n\n            if (event.altKey || event.ctrlKey) {\n                return;\n            }\n            keyCode = $.ui.keyCode;\n            toFocus = false;\n            enabledTriggers = [];\n\n            $.each(this.triggers, function () {\n                if (!self.collapsibles.eq(self.triggers.index($(this))).collapsible('option', 'disabled')) {\n                    enabledTriggers.push(this);\n                }\n            });\n            length = $(enabledTriggers).length;\n            currentIndex = $(enabledTriggers).index(event.target);\n\n            /**\n             * @param {String} direction\n             * @return {*}\n             */\n            nextToFocus = function (direction) {\n                if (length > 0) {\n                    if (direction === 'right') {\n                        toFocusIndex = (currentIndex + 1) % length;\n                    } else {\n                        toFocusIndex = (currentIndex + length - 1) % length;\n                    }\n\n                    return enabledTriggers[toFocusIndex];\n                }\n\n                return event.target;\n            };\n\n            switch (event.keyCode) {\n                case keyCode.RIGHT:\n                case keyCode.DOWN:\n                    toFocus = nextToFocus('right');\n                    break;\n\n                case keyCode.LEFT:\n                case keyCode.UP:\n                    toFocus = nextToFocus('left');\n                    break;\n\n                case keyCode.HOME:\n                    toFocus = enabledTriggers[0];\n                    break;\n\n                case keyCode.END:\n                    toFocus = enabledTriggers[length - 1];\n                    break;\n            }\n\n            if (toFocus) {\n                toFocusIndex = this.triggers.index(toFocus);\n                $(event.target).attr('tabIndex', -1);\n                $(toFocus).attr('tabIndex', 0);\n                toFocus.focus();\n\n                if (this.options.openOnFocus) {\n                    this.activate(toFocusIndex);\n                }\n                event.preventDefault();\n            }\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            var events = {\n                keydown: '_keydown'\n            };\n\n            this._off(this.triggers);\n            this._on(this.triggers, events);\n        }\n    });\n\n    return $.mage.tabs;\n});\n","mage/dropdown.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/dialog',\n    'mage/translate'\n], function ($) {\n    'use strict';\n\n    var timer = null;\n\n    /**\n     * Dropdown Widget - this widget is a wrapper for the jQuery UI Dialog\n     */\n    $.widget('mage.dropdownDialog', $.ui.dialog, {\n        options: {\n            triggerEvent: 'click',\n            triggerClass: null,\n            parentClass: null,\n            triggerTarget: null,\n            defaultDialogClass: 'mage-dropdown-dialog',\n            dialogContentClass: null,\n            shadowHinter: null,\n            closeOnMouseLeave: true,\n            closeOnClickOutside: true,\n            minHeight: null,\n            minWidth: null,\n            width: null,\n            modal: false,\n            timeout: null,\n            autoOpen: false,\n            createTitleBar: false,\n            autoPosition: false,\n            autoSize: false,\n            draggable: false,\n            resizable: false,\n            bodyClass: '',\n            buttons: [\n                {\n                    'class': 'action close',\n                    'text': $.mage.__('Close'),\n\n                    /**\n                     * Click action.\n                     */\n                    'click': function () {\n                        $(this).dropdownDialog('close');\n                    }\n                }\n            ]\n        },\n\n        /**\n         * extend default functionality to bind the opener for dropdown\n         * @private\n         */\n        _create: function () {\n            var _self = this;\n\n            this._super();\n            this.uiDialog.addClass(this.options.defaultDialogClass);\n\n            if (_self.options.triggerTarget) {\n                $(_self.options.triggerTarget).on(_self.options.triggerEvent, function (event) {\n                    event.preventDefault();\n                    event.stopPropagation();\n\n                    if (!_self._isOpen) {\n                        $('.' + _self.options.defaultDialogClass + ' > .ui-dialog-content').dropdownDialog('close');\n                        _self.open();\n                    } else {\n                        _self.close(event);\n                    }\n                });\n            }\n\n            if (_self.options.shadowHinter) {\n                _self.hinter = $('<div class=\"' + _self.options.shadowHinter + '\"></div>');\n                _self.element.append(_self.hinter);\n            }\n        },\n\n        /**\n         * Extend default functionality to close the dropdown\n         * with custom delay on mouse out and also to close when clicking outside\n         */\n        open: function () {\n            var _self = this;\n\n            this._super();\n\n            if (_self.options.dialogContentClass) {\n                _self.element.addClass(_self.options.dialogContentClass);\n            }\n\n            if (_self.options.closeOnMouseLeave) {\n\n                this._mouseEnter(_self.uiDialog);\n                this._mouseLeave(_self.uiDialog);\n\n                if (_self.options.triggerTarget) {\n                    this._mouseLeave($(_self.options.triggerTarget));\n                }\n            }\n\n            if (_self.options.closeOnClickOutside) {\n                $('body').on('click.outsideDropdown', function (event) {\n                    if (_self._isOpen && !$(event.target).closest('.ui-dialog').length) {\n                        if (timer) {\n                            clearTimeout(timer);\n                        }\n                        _self.close(event);\n                    }\n                });\n            }\n            // adding the class on the opener and parent element for dropdown\n            if (_self.options.triggerClass) {\n                $(_self.options.triggerTarget).addClass(_self.options.triggerClass);\n            }\n\n            if (_self.options.parentClass) {\n                $(_self.options.appendTo).addClass(_self.options.parentClass);\n            }\n\n            if (_self.options.bodyClass) {\n                $('body').addClass(_self.options.bodyClass);\n            }\n\n            if (_self.options.shadowHinter) {\n                _self._setShadowHinterPosition();\n            }\n        },\n\n        /**\n         * extend default functionality to reset the timer and remove the active class for opener\n         */\n        close: function () {\n            this._super();\n\n            if (this.options.dialogContentClass) {\n                this.element.removeClass(this.options.dialogContentClass);\n            }\n\n            if (this.options.triggerClass) {\n                $(this.options.triggerTarget).removeClass(this.options.triggerClass);\n            }\n\n            if (this.options.parentClass) {\n                $(this.options.appendTo).removeClass(this.options.parentClass);\n            }\n\n            if (this.options.bodyClass) {\n                $('body').removeClass(this.options.bodyClass);\n            }\n\n            if (timer) {\n                clearTimeout(timer);\n            }\n\n            if (this.options.triggerTarget) {\n                $(this.options.triggerTarget).off('mouseleave');\n            }\n            this.uiDialog.off('mouseenter');\n            this.uiDialog.off('mouseleave');\n            $('body').off('click.outsideDropdown');\n        },\n\n        /**\n         * _setShadowHinterPosition\n         * @private\n         */\n        _setShadowHinterPosition: function () {\n            var _self = this,\n                offset;\n\n            offset = _self.options.position.of.offset().left -\n                _self.element.offset().left +\n                _self.options.position.of.outerWidth() / 2;\n            offset = isNaN(offset) ? 0 : Math.floor(offset);\n            _self.hinter.css('left', offset);\n        },\n\n        /**\n         * @private\n         */\n        _position: function () {\n            if (this.options.autoPosition) {\n                this._super();\n            }\n        },\n\n        /**\n         * @private\n         */\n        _createTitlebar: function () {\n            if (this.options.createTitleBar) {\n                this._super();\n            } else {\n                // the title bar close button is referenced\n                // in _focusTabbable function, so to prevent errors it must be declared\n                this.uiDialogTitlebarClose = $('<div></div>');\n            }\n        },\n\n        /**\n         * @private\n         */\n        _size: function () {\n            if (this.options.autoSize) {\n                this._super();\n            }\n        },\n\n        /**\n         * @param {Object} handler\n         * @private\n         */\n        _mouseLeave: function (handler) {\n            var _self = this;\n\n            handler.on('mouseleave', function (event) {\n                event.stopPropagation();\n\n                if (_self._isOpen) {\n                    if (timer) {\n                        clearTimeout(timer);\n                    }\n                    timer = setTimeout(function (e) {\n                        _self.close(e);\n                    }, _self.options.timeout);\n                }\n            });\n        },\n\n        /**\n         * @param {Object} handler\n         * @private\n         */\n        _mouseEnter: function (handler) {\n            handler.on('mouseenter', function (event) {\n                event.stopPropagation();\n\n                if (timer) {\n                    clearTimeout(timer);\n                }\n            });\n        },\n\n        /**\n         * @param {String} key\n         * @param {*} value\n         * @private\n         */\n        _setOption: function (key, value) {\n            this._super(key, value);\n\n            if (key === 'triggerTarget') {\n                this.options.triggerTarget = value;\n            }\n        }\n    });\n\n    return $.mage.dropdownDialog;\n});\n","mage/tooltip.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\ndefine([\n    'jquery',\n    'jquery-ui-modules/tooltip'\n], function ($) {\n    'use strict';\n\n    //Widget Wrapper\n    $.widget('mage.tooltip', $.ui.tooltip, {});\n\n    return $.mage.tooltip;\n});\n","mage/toggle.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.toggleAdvanced', {\n        options: {\n            baseToggleClass: 'active' // Class used to be toggled on clicked element\n        },\n\n        /**\n         * Toggle creation\n         * @private\n         */\n        _create: function () {\n            this.beforeCreate();\n            this._bindCore();\n            this.afterCreate();\n        },\n\n        /**\n         *  Core bound events & setup\n         * @protected\n         */\n        _bindCore: function () {\n            var widget = this;\n\n            this.element.on('click', $.proxy(function (e) {\n                widget._onClick();\n                e.preventDefault();\n            }, this));\n        },\n\n        /**\n         * Binding Click event\n         *\n         * @protected\n         */\n        _onClick: function () {\n            this._prepareOptions();\n            this._toggleSelectors();\n        },\n\n        /**\n         * Method used to look for data attributes to override default options\n         *\n         * @protected\n         */\n        _prepareOptions: function () {\n            this.options.baseToggleClass = this.element.data('base-toggle-class') ?\n                this.element.data('base-toggle-class') : this.options.baseToggleClass;\n        },\n\n        /**\n         * Method responsible for hiding and revealing specified DOM elements\n         * Toggle the class on clicked element\n         *\n         * @protected\n         */\n        _toggleSelectors: function () {\n            this.element.toggleClass(this.options.baseToggleClass);\n        },\n\n        /**\n         * Method used to inject 3rd party functionality before create\n         * @public\n         */\n        beforeCreate: function () {},\n\n        /**\n         * Method used to inject 3rd party functionality after create\n         * @public\n         */\n        afterCreate: function () {}\n    });\n\n    // Extension for mage.toggle - Adding selectors support for other DOM elements we wish to toggle\n    $.widget('mage.toggleAdvanced', $.mage.toggleAdvanced, {\n\n        options: {\n            selectorsToggleClass: 'hidden',    // Class used to be toggled on selectors DOM elements\n            toggleContainers: null\n        },\n\n        /**\n         * Method responsible for hiding and revealing specified DOM elements\n         * If data-toggle-selectors attribute is present - toggle will be done on these selectors\n         * Otherwise we toggle the class on clicked element\n         *\n         * @protected\n         * @override\n         */\n        _toggleSelectors: function () {\n            this._super();\n\n            if (this.options.toggleContainers) {\n                $(this.options.toggleContainers).toggleClass(this.options.selectorsToggleClass);\n            } else {\n                this.element.toggleClass(this.options.baseToggleClass);\n            }\n        },\n\n        /**\n         * Method used to look for data attributes to override default options\n         *\n         * @protected\n         * @override\n         */\n        _prepareOptions: function () {\n            this.options.selectorsToggleClass = this.element.data('selectors-toggle-class') ?\n                this.element.data('selectors-toggle-class') : this.options.selectorsToggleClass;\n            this.options.toggleContainers = this.element.data('toggle-selectors') ?\n                this.element.data('toggle-selectors') : this.options.toggleContainers;\n            this._super();\n        }\n    });\n\n    // Extension for mage.toggle - Adding label toggle\n    $.widget('mage.toggleAdvanced', $.mage.toggleAdvanced, {\n\n        options: {\n            newLabel: null,             // Text of the new label to be used on toggle\n            curLabel: null,             // Text of the old label to be used on toggle\n            currentLabelElement: null   // Current label container\n        },\n\n        /**\n         * Binding Click event\n         *\n         * @protected\n         * @override\n         */\n        _onClick: function () {\n            this._super();\n            this._toggleLabel();\n        },\n\n        /**\n         * Method responsible for replacing clicked element labels\n         * @protected\n         */\n        _toggleLabel: function () {\n            var cachedLabel, currentLabelSelector;\n\n            if (this.options.newLabel) {\n                cachedLabel = this.options.newLabel;\n                currentLabelSelector = this.options.currentLabelElement ?\n                        $(this.options.currentLabelElement) : this.element;\n\n                this.element.data('toggle-label', this.options.curLabel);\n                currentLabelSelector.html(this.options.newLabel);\n\n                this.options.curLabel = this.options.newLabel;\n                this.options.newLabel = cachedLabel;\n            }\n        },\n\n        /**\n         * Method used to look for data attributes to override default options\n         *\n         * @protected\n         * @override\n         */\n        _prepareOptions: function () {\n            this.options.newLabel = this.element.data('toggle-label') ?\n                this.element.data('toggle-label') : this.options.newLabel;\n\n            this.options.currentLabelElement = this.element.data('current-label-el') ?\n                this.element.data('current-label-el') : this.options.currentLabelElement;\n\n            if (!this.options.currentLabelElement) {\n                this.options.currentLabelElement = this.element;\n            }\n\n            this.options.curLabel = $(this.options.currentLabelElement).html();\n\n            this._super();\n        }\n    });\n\n    return $.mage.toggleAdvanced;\n});\n","mage/fieldset-controls.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    /**\n     * This widget will allow a control with the fieldsetResetControl widget attached to reset a set of input fields.\n     * The input fields to reset are defined by the inputSelector selector. The widget will store a clone of the fields\n     * on create, and on trigger of fieldsetReset event it resets the defined fields. The event is triggered by the\n     * reset control widget.\n     *\n     * For inputs of type file, the whole dom element is replaced as changing the value is a security violation\n     * For inputs of type checkbox or radio, the checked attribute is added or removed as appropriate\n     * For all others the jquery .val method is used to update to value to the original.\n     */\n    $.widget('mage.fieldsetControls', {\n        original: undefined,\n        options: {\n            inputSelector: '[data-reset=\"true\"]'\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            this.original = this.element.find(this.options.inputSelector).clone(true);\n            this._bind();\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            this._on({\n                'fieldsetReset': '_onReset'\n            });\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @private\n         */\n        _onReset: function (e) {\n            var items;\n\n            e.stopPropagation();\n            // find all the ones we have to remove\n            items = this.element.find(this.options.inputSelector);\n            // loop over replacing each one.\n            items.each($.proxy(function (index, item) {\n                if ($(item).attr('type') == 'file') { //eslint-disable-line eqeqeq\n                    // Replace the current one we found with a clone of the original saved earlier\n                    $(item).replaceWith($(this.original[index]).clone(true));\n                } else if ($(item).attr('type') == 'checkbox' || $(item).attr('type') == 'radio') { //eslint-disable-line\n                    // Return to original state.\n                    if ($(this.original[index]).attr('checked') === undefined) {\n                        $(item).removeAttr('checked');\n                    } else {\n                        $(item).attr('checked', $(this.original[index]).attr('checked'));\n                    }\n                } else {\n                    // Replace the value with the original\n                    $(item).val($(this.original[index]).val());\n                }\n            }, this));\n        }\n    });\n\n    $.widget('mage.fieldsetResetControl', {\n        /**\n         * @private\n         */\n        _create: function () {\n            this._bind();\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            this._on({\n                click: '_onClick'\n            });\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @private\n         */\n        _onClick: function (e) {\n            e.stopPropagation();\n            $(this.element).trigger('fieldsetReset');\n        }\n    });\n\n    return {\n        fieldsetControls: $.mage.fieldsetControls,\n        fieldsetResetControl: $.mage.fieldsetResetControl\n    };\n});\n","mage/validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'moment',\n    'mageUtils',\n    'jquery-ui-modules/widget',\n    'jquery/validate',\n    'mage/translate'\n], function ($, moment, utils) {\n    'use strict';\n\n    var creditCartTypes, rules, showLabel, originValidateDelegate;\n\n    $.extend(true, $, {\n        // @TODO: Move methods 'isEmpty', 'isEmptyNoTrim', 'parseNumber', 'stripHtml' in file with utility functions\n        mage: {\n            /**\n             * Check if string is empty with trim\n             * @param {String} value\n             */\n            isEmpty: function (value) {\n                return value === '' || value === undefined ||\n                    value == null || value.length === 0 || /^\\s+$/.test(value);\n            },\n\n            /**\n             * Check if string is empty no trim\n             * @param {String} value\n             */\n            isEmptyNoTrim: function (value) {\n                return value === '' || value == null || value.length === 0;\n            },\n\n            /**\n             * Checks if {value} is between numbers {from} and {to}\n             * @param {String} value\n             * @param {String} from\n             * @param {String} to\n             * @returns {Boolean}\n             */\n            isBetween: function (value, from, to) {\n                return ($.mage.isEmpty(from) || value >= $.mage.parseNumber(from)) &&\n                    ($.mage.isEmpty(to) || value <= $.mage.parseNumber(to));\n            },\n\n            /**\n             * Parse price string\n             * @param {String} value\n             */\n            parseNumber: function (value) {\n                var isDot, isComa;\n\n                if (typeof value !== 'string') {\n                    return parseFloat(value);\n                }\n                isDot = value.indexOf('.');\n                isComa = value.indexOf(',');\n\n                if (isDot !== -1 && isComa !== -1) {\n                    if (isComa > isDot) {\n                        value = value.replace('.', '').replace(',', '.');\n                    } else {\n                        value = value.replace(',', '');\n                    }\n                } else if (isComa !== -1) {\n                    value = value.replace(',', '.');\n                }\n\n                return parseFloat(value);\n            },\n\n            /**\n             * Removes HTML tags and space characters, numbers and punctuation.\n             *\n             * @param {String} value - Value being stripped.\n             * @return {String}\n             */\n            stripHtml: function (value) {\n                return value.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' ')\n                    .replace(/[0-9.(),;:!?%#$'\"_+=\\/-]*/g, '');\n            }\n        }\n    });\n\n    /**\n     * @param {String} name\n     * @param {*} method\n     * @param {*} message\n     * @param {*} dontSkip\n     */\n    $.validator.addMethod = function (name, method, message, dontSkip) {\n        $.validator.methods[name] = method;\n        $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];\n\n        if (method.length < 3 || dontSkip) {\n            $.validator.addClassRules(name, $.validator.normalizeRule(name));\n        }\n    };\n\n    /**\n     * Javascript object with credit card types\n     * 0 - regexp for card number\n     * 1 - regexp for cvn\n     * 2 - check or not credit card number trough Luhn algorithm by\n     */\n    creditCartTypes = {\n        'SO': [\n            new RegExp('^(6334[5-9]([0-9]{11}|[0-9]{13,14}))|(6767([0-9]{12}|[0-9]{14,15}))$'),\n            new RegExp('^([0-9]{3}|[0-9]{4})?$'),\n            true\n        ],\n        'SM': [\n            new RegExp('(^(5[0678])[0-9]{11,18}$)|(^(6[^05])[0-9]{11,18}$)|' +\n                '(^(601)[^1][0-9]{9,16}$)|(^(6011)[0-9]{9,11}$)|(^(6011)[0-9]{13,16}$)|' +\n                '(^(65)[0-9]{11,13}$)|(^(65)[0-9]{15,18}$)|(^(49030)[2-9]([0-9]{10}$|[0-9]{12,13}$))|' +\n                '(^(49033)[5-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49110)[1-2]([0-9]{10}$|[0-9]{12,13}$))|' +\n                '(^(49117)[4-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49118)[0-2]([0-9]{10}$|[0-9]{12,13}$))|' +\n                '(^(4936)([0-9]{12}$|[0-9]{14,15}$))'), new RegExp('^([0-9]{3}|[0-9]{4})?$'),\n            true\n        ],\n        'VI': [new RegExp('^4[0-9]{12}([0-9]{3})?$'), new RegExp('^[0-9]{3}$'), true],\n        'MC': [\n            new RegExp('^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$'),\n            new RegExp('^[0-9]{3}$'),\n            true\n        ],\n        'AE': [new RegExp('^3[47][0-9]{13}$'), new RegExp('^[0-9]{4}$'), true],\n        'DI': [new RegExp('^(6011(0|[2-4]|74|7[7-9]|8[6-9]|9)|6(4[4-9]|5))\\\\d*$'), new RegExp('^[0-9]{3}$'), true],\n        'JCB': [new RegExp('^35(2[8-9]|[3-8])\\\\d*$'), new RegExp('^[0-9]{3}$'), true],\n        'DN': [new RegExp('^(3(0[0-5]|095|6|[8-9]))\\\\d*$'), new RegExp('^[0-9]{3}$'), true],\n        'UN': [\n            new RegExp('^(622(1(2[6-9]|[3-9])|[3-8]|9([[0-1]|2[0-5]))|62[4-6]|628([2-8]))\\\\d*?$'),\n            new RegExp('^[0-9]{3}$'),\n            true\n        ],\n        'MI': [new RegExp('^(5(0|[6-9])|63|67(?!59|6770|6774))\\\\d*$'), new RegExp('^[0-9]{3}$'), true],\n        'MD': [new RegExp('^6759(?!24|38|40|6[3-9]|70|76)|676770|676774\\\\d*$'), new RegExp('^[0-9]{3}$'), true]\n    };\n\n    /**\n     * validate credit card number using mod10\n     * @param {String} s\n     * @return {Boolean}\n     */\n    function validateCreditCard(s) {\n        // remove non-numerics\n        var v = '0123456789',\n            w = '',\n            i, j, k, m, c, a, x;\n\n        for (i = 0; i < s.length; i++) {\n            x = s.charAt(i);\n\n            if (v.indexOf(x, 0) !== -1) {\n                w += x;\n            }\n        }\n        // validate number\n        j = w.length / 2;\n        k = Math.floor(j);\n        m = Math.ceil(j) - k;\n        c = 0;\n\n        for (i = 0; i < k; i++) {\n            a = w.charAt(i * 2 + m) * 2;\n            c += a > 9 ? Math.floor(a / 10 + a % 10) : a;\n        }\n\n        for (i = 0; i < k + m; i++) {\n            c += w.charAt(i * 2 + 1 - m) * 1;\n        }\n\n        return c % 10 === 0;\n    }\n\n    /**\n     * validate all table required inputs at once, using single hidden input\n     * @param {String} value\n     * @param {HTMLElement} element\n     *\n     * @return {Boolean}\n     */\n    function tableSingleValidation(value, element) {\n        var empty = $(element).closest('table')\n            .find('input.required-option:visible')\n            .filter(function (i, el) {\n                if ($(el).is('disabled')) {\n                    return $.mage.isEmpty(el.value);\n                }\n            })\n            .length;\n\n        return empty === 0;\n    }\n\n    /**\n     *\n     * @param {float} qty\n     * @param {float} qtyIncrements\n     * @returns {float}\n     */\n    function resolveModulo(qty, qtyIncrements) {\n        var divideEpsilon = 10000,\n            epsilon,\n            remainder;\n\n        while (qtyIncrements < 1) {\n            qty *= 10;\n            qtyIncrements *= 10;\n        }\n\n        epsilon = qtyIncrements / divideEpsilon;\n        remainder = qty % qtyIncrements;\n\n        if (Math.abs(remainder - qtyIncrements) < epsilon ||\n            Math.abs(remainder) < epsilon) {\n            remainder = 0;\n        }\n\n        return remainder;\n    }\n\n    /**\n     * Collection of validation rules including rules from additional-methods.js\n     * @type {Object}\n     */\n    rules = {\n        'max-words': [\n            function (value, element, params) {\n                return this.optional(element) || $.mage.stripHtml(value).match(/\\b\\w+\\b/g).length <= params;\n            },\n            $.mage.__('Please enter {0} words or less.')\n        ],\n        'min-words': [\n            function (value, element, params) {\n                return this.optional(element) || $.mage.stripHtml(value).match(/\\b\\w+\\b/g).length >= params;\n            },\n            $.mage.__('Please enter at least {0} words.')\n        ],\n        'range-words': [\n            function (value, element, params) {\n                return this.optional(element) ||\n                    $.mage.stripHtml(value).match(/\\b\\w+\\b/g).length >= params[0] &&\n                    value.match(/bw+b/g).length < params[1];\n            },\n            $.mage.__('Please enter between {0} and {1} words.')\n        ],\n        'letters-with-basic-punc': [\n            function (value, element) {\n                return this.optional(element) || /^[a-z\\-.,()'\\\"\\s]+$/i.test(value);\n            },\n            $.mage.__('Letters or punctuation only please')\n        ],\n        'alphanumeric': [\n            function (value, element) {\n                return this.optional(element) || /^\\w+$/i.test(value);\n            },\n            $.mage.__('Letters, numbers, spaces or underscores only please')\n        ],\n        'letters-only': [\n            function (value, element) {\n                return this.optional(element) || /^[a-z]+$/i.test(value);\n            },\n            $.mage.__('Letters only please')\n        ],\n        'no-whitespace': [\n            function (value, element) {\n                return this.optional(element) || /^\\S+$/i.test(value);\n            },\n            $.mage.__('No white space please')\n        ],\n        'no-marginal-whitespace': [\n            function (value, element) {\n                return this.optional(element) || !/^\\s+|\\s+$/i.test(value);\n            },\n            $.mage.__('No marginal white space please')\n        ],\n        'zip-range': [\n            function (value, element) {\n                return this.optional(element) || /^90[2-5]-\\d{2}-\\d{4}$/.test(value);\n            },\n            $.mage.__('Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx')\n        ],\n        'integer': [\n            function (value, element) {\n                return this.optional(element) || /^-?\\d+$/.test(value);\n            },\n            $.mage.__('A positive or negative non-decimal number please')\n        ],\n        'vinUS': [\n            function (v) {\n                var i, n, d, f, cd, cdv, LL, VL, FL, rs;\n\n                /* eslint-disable max-depth */\n                if (v.length !== 17) {\n                    return false;\n                }\n\n                LL = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L',\n                    'M', 'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];\n                VL = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9];\n                FL = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2];\n                rs = 0;\n\n                for (i = 0; i < 17; i++) {\n                    f = FL[i];\n                    d = v.slice(i, i + 1);\n\n                    if (i === 8) {\n                        cdv = d;\n                    }\n\n                    if (!isNaN(d)) {\n                        d *= f;\n                    } else {\n                        for (n = 0; n < LL.length; n++) {\n                            if (d.toUpperCase() === LL[n]) {\n                                d = VL[n];\n                                d *= f;\n\n                                if (isNaN(cdv) && n === 8) {\n                                    cdv = LL[n];\n                                }\n                                break;\n                            }\n                        }\n                    }\n                    rs += d;\n                }\n\n                /* eslint-enable max-depth */\n                cd = rs % 11;\n\n                if (cd === 10) {\n                    cd = 'X';\n                }\n\n                if (cd === cdv) {\n                    return true;\n                }\n\n                return false;\n            },\n            $.mage.__('The specified vehicle identification number (VIN) is invalid.')\n        ],\n        'dateITA': [\n            function (value, element) {\n                var check = false,\n                    re = /^\\d{1,2}\\/\\d{1,2}\\/\\d{4}$/,\n                    adata, gg, mm, aaaa, xdata;\n\n                if (re.test(value)) {\n                    adata = value.split('/');\n                    gg = parseInt(adata[0], 10);\n                    mm = parseInt(adata[1], 10);\n                    aaaa = parseInt(adata[2], 10);\n                    xdata = new Date(aaaa, mm - 1, gg);\n\n                    if (xdata.getFullYear() === aaaa &&\n                        xdata.getMonth() === mm - 1 &&\n                        xdata.getDate() === gg\n                    ) {\n                        check = true;\n                    } else {\n                        check = false;\n                    }\n                } else {\n                    check = false;\n                }\n\n                return this.optional(element) || check;\n            },\n            $.mage.__('Please enter a correct date')\n        ],\n        'dateNL': [\n            function (value, element) {\n                return this.optional(element) || /^\\d\\d?[\\.\\/-]\\d\\d?[\\.\\/-]\\d\\d\\d?\\d?$/.test(value);\n            },\n            'Vul hier een geldige datum in.'\n        ],\n        'time': [\n            function (value, element) {\n                return this.optional(element) || /^([01]\\d|2[0-3])(:[0-5]\\d){0,2}$/.test(value);\n            },\n            $.mage.__('Please enter a valid time, between 00:00 and 23:59')\n        ],\n        'time12h': [\n            function (value, element) {\n                return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\\d){0,2}(\\s[AP]M))$/i.test(value);\n            },\n            $.mage.__('Please enter a valid time, between 00:00 am and 12:00 pm')\n        ],\n        'phoneUS': [\n            function (phoneNumber, element) {\n                phoneNumber = phoneNumber.replace(/\\s+/g, '');\n\n                return this.optional(element) || phoneNumber.length > 9 &&\n                    phoneNumber.match(/^(1-?)?(\\([2-9]\\d{2}\\)|[2-9]\\d{2})-?[2-9]\\d{2}-?\\d{4}$/);\n            },\n            $.mage.__('Please specify a valid phone number')\n        ],\n        'phoneUK': [\n            function (phoneNumber, element) {\n                return this.optional(element) || phoneNumber.length > 9 &&\n                    phoneNumber.match(/^(\\(?(0|\\+44)[1-9]{1}\\d{1,4}?\\)?\\s?\\d{3,4}\\s?\\d{3,4})$/);\n            },\n            $.mage.__('Please specify a valid phone number')\n        ],\n        'mobileUK': [\n            function (phoneNumber, element) {\n                return this.optional(element) || phoneNumber.length > 9 &&\n                    phoneNumber.match(/^((0|\\+44)7\\d{3}\\s?\\d{6})$/);\n            },\n            $.mage.__('Please specify a valid mobile number')\n        ],\n        'stripped-min-length': [\n            function (value, element, param) {\n                return value.length >= param;\n            },\n            $.mage.__('Please enter at least {0} characters')\n        ],\n\n        /* detect chars that would require more than 3 bytes */\n        'validate-no-utf8mb4-characters': [\n            function (value) {\n                var validator = this,\n                    message = $.mage.__('Please remove invalid characters: {0}.'),\n                    matches = value.match(/(?:[\\uD800-\\uDBFF][\\uDC00-\\uDFFF])/g),\n                    result = matches === null;\n\n                if (!result) {\n                    validator.charErrorMessage = message.replace('{0}', matches.join());\n                }\n\n                return result;\n            }, function () {\n                return this.charErrorMessage;\n            }\n        ],\n\n        /* eslint-disable max-len */\n        'email2': [\n            function (value, element) {\n                return this.optional(element) ||\n                    /^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)*(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$/i.test(value);\n            },\n            $.validator.messages.email\n        ],\n        'url2': [\n            function (value, element) {\n                return this.optional(element) || /^(https?|ftp):\\/\\/(((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)*(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.test(value);\n            },\n            $.validator.messages.url\n        ],\n\n        /* eslint-enable max-len */\n        'credit-card-types': [\n            function (value, element, param) {\n                var validTypes;\n\n                if (/[^0-9-]+/.test(value)) {\n                    return false;\n                }\n                value = value.replace(/\\D/g, '');\n\n                validTypes = 0x0000;\n\n                if (param.mastercard) {\n                    validTypes |= 0x0001;\n                }\n\n                if (param.visa) {\n                    validTypes |= 0x0002;\n                }\n\n                if (param.amex) {\n                    validTypes |= 0x0004;\n                }\n\n                if (param.dinersclub) {\n                    validTypes |= 0x0008;\n                }\n\n                if (param.enroute) {\n                    validTypes |= 0x0010;\n                }\n\n                if (param.discover) {\n                    validTypes |= 0x0020;\n                }\n\n                if (param.jcb) {\n                    validTypes |= 0x0040;\n                }\n\n                if (param.unknown) {\n                    validTypes |= 0x0080;\n                }\n\n                if (param.all) {\n                    validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;\n                }\n\n                if (validTypes & 0x0001 && /^(51|52|53|54|55)/.test(value)) { //mastercard\n                    return value.length === 16;\n                }\n\n                if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa\n                    return value.length === 16;\n                }\n\n                if (validTypes & 0x0004 && /^(34|37)/.test(value)) { //amex\n                    return value.length === 15;\n                }\n\n                if (validTypes & 0x0008 && /^(300|301|302|303|304|305|36|38)/.test(value)) { //dinersclub\n                    return value.length === 14;\n                }\n\n                if (validTypes & 0x0010 && /^(2014|2149)/.test(value)) { //enroute\n                    return value.length === 15;\n                }\n\n                if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover\n                    return value.length === 16;\n                }\n\n                if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb\n                    return value.length === 16;\n                }\n\n                if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb\n                    return value.length === 15;\n                }\n\n                if (validTypes & 0x0080) { //unknown\n                    return true;\n                }\n\n                return false;\n            },\n            $.mage.__('Please enter a valid credit card number.')\n        ],\n\n        /* eslint-disable max-len */\n        'ipv4': [\n            function (value, element) {\n                return this.optional(element) ||\n                    /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i.test(value);\n            },\n            $.mage.__('Please enter a valid IP v4 address.')\n        ],\n        'ipv6': [\n            function (value, element) {\n                return this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value);\n            },\n            $.mage.__('Please enter a valid IP v6 address.')\n        ],\n\n        /* eslint-enable max-len */\n        'pattern': [\n            function (value, element, param) {\n                return this.optional(element) || new RegExp(param).test(value);\n            },\n            $.mage.__('Invalid format.')\n        ],\n        'allow-container-className': [\n            function (element) {\n                if (element.type === 'radio' || element.type === 'checkbox') {\n                    return $(element).hasClass('change-container-classname');\n                }\n            },\n            ''\n        ],\n        'validate-no-html-tags': [\n            function (value) {\n                return !/<(\\/)?\\w+/.test(value);\n            },\n            $.mage.__('HTML tags are not allowed.')\n        ],\n        'validate-select': [\n            function (value) {\n                return value !== 'none' && value != null && value.length !== 0;\n            },\n            $.mage.__('Please select an option.')\n        ],\n        'validate-no-empty': [\n            function (value) {\n                return !$.mage.isEmpty(value);\n            },\n            $.mage.__('Empty Value.')\n        ],\n        'validate-alphanum-with-spaces': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^[a-zA-Z0-9 ]+$/.test(v);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.')\n        ],\n        'validate-data': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^[A-Za-z]+[A-Za-z0-9_]+$/.test(v);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.') //eslint-disable-line max-len\n        ],\n        'validate-street': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^[ \\w]{3,}([A-Za-z]\\.)?([ \\w]*\\#\\d+)?(\\r\\n| )[ \\w]{3,}/.test(v);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9), spaces and \"#\" in this field.')\n        ],\n        'validate-phoneStrict': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^(\\()?\\d{3}(\\))?(-|\\s)?\\d{3}(-|\\s)\\d{4}$/.test(v);\n            },\n            $.mage.__('Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.')\n        ],\n        'validate-phoneLax': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) ||\n                    /^((\\d[\\-. ]?)?((\\(\\d{3}\\))|\\d{3}))?[\\-. ]?\\d{3}[\\-. ]?\\d{4}$/.test(v);\n            },\n            $.mage.__('Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.')\n        ],\n        'validate-fax': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^(\\()?\\d{3}(\\))?(-|\\s)?\\d{3}(-|\\s)\\d{4}$/.test(v);\n            },\n            $.mage.__('Please enter a valid fax number (Ex: 123-456-7890).')\n        ],\n        'validate-email': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^([a-z0-9,!\\#\\$%&'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z0-9,!\\#\\$%&'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*@([a-z0-9-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z0-9-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*\\.(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]){2,})$/i.test(v); //eslint-disable-line max-len\n            },\n            $.mage.__('Please enter a valid email address (Ex: johndoe@domain.com).')\n        ],\n        //replace jquery.validation.js email validation rule\n        'email' : [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^([a-z0-9,!\\#\\$%&'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z0-9,!\\#\\$%&'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*@([a-z0-9-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z0-9-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*\\.(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]){2,})$/i.test(v); //eslint-disable-line max-len\n            },\n            $.mage.__('Please enter a valid email address.')\n        ],\n        'validate-emailSender': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^(?!.*:)[\\S ]+$/.test(v);\n            },\n            $.mage.__('Please use only visible characters and spaces. The colon character is not allowed.')\n        ],\n        'validate-password': [\n            function (v) {\n                var pass;\n\n                if (v == null) {\n                    return false;\n                }\n                //strip leading and trailing spaces\n                pass = v.trim();\n\n                if (!pass.length) {\n                    return true;\n                }\n\n                return !(pass.length > 0 && pass.length < 6);\n            },\n            $.mage.__('Please enter 6 or more characters. Leading and trailing spaces will be ignored.')\n        ],\n        'validate-admin-password': [\n            function (v) {\n                var pass;\n\n                if (v == null) {\n                    return false;\n                }\n                pass = v.trim();\n                // strip leading and trailing spaces\n                if (pass.length === 0) {\n                    return true;\n                }\n\n                if (!/[a-z]/i.test(v) || !/[0-9]/.test(v)) {\n                    return false;\n                }\n\n                if (pass.length < 7) {\n                    return false;\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter 7 or more characters, using both numeric and alphabetic.')\n        ],\n        'validate-customer-password': [\n            function (v, elm) {\n                var validator = this,\n                    counter = 0,\n                    passwordMinLength = $(elm).data('password-min-length'),\n                    passwordMinCharacterSets = $(elm).data('password-min-character-sets'),\n                    pass = v.trim(),\n                    result = pass.length >= passwordMinLength;\n\n                if (result === false) {\n                    validator.passwordErrorMessage = $.mage.__('Minimum length of this field must be equal or greater than %1 symbols. Leading and trailing spaces will be ignored.').replace('%1', passwordMinLength); //eslint-disable-line max-len\n\n                    return result;\n                }\n\n                if (pass.match(/\\d+/)) {\n                    counter++;\n                }\n\n                if (pass.match(/[a-z]+/)) {\n                    counter++;\n                }\n\n                if (pass.match(/[A-Z]+/)) {\n                    counter++;\n                }\n\n                if (pass.match(/[^a-zA-Z0-9]+/)) {\n                    counter++;\n                }\n\n                if (counter < passwordMinCharacterSets) {\n                    result = false;\n                    validator.passwordErrorMessage = $.mage.__('Minimum of different classes of characters in password is %1. Classes of characters: Lower Case, Upper Case, Digits, Special Characters.').replace('%1', passwordMinCharacterSets); //eslint-disable-line max-len\n                }\n\n                return result;\n            }, function () {\n                return this.passwordErrorMessage;\n            }\n        ],\n        'validate-url': [\n            function (v) {\n                if ($.mage.isEmptyNoTrim(v)) {\n                    return true;\n                }\n                v = (v || '').replace(/^\\s+/, '').replace(/\\s+$/, '');\n\n                return (/^(http|https|ftp):\\/\\/(([A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))(\\.[A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))*)(:(\\d+))?(\\/[A-Z0-9~](([A-Z0-9_~-]|\\.)*[A-Z0-9~]|))*\\/?(.*)?$/i).test(v); //eslint-disable-line max-len\n\n            },\n            $.mage.__('Please enter a valid URL. Protocol is required (http://, https:// or ftp://).')\n        ],\n        'validate-clean-url': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^(http|https|ftp):\\/\\/(([A-Z0-9][A-Z0-9_-]*)(\\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\\d+))?\\/?/i.test(v) || /^(www)((\\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\\d+))?\\/?/i.test(v); //eslint-disable-line max-len\n\n            },\n            $.mage.__('Please enter a valid URL. For example http://www.example.com or www.example.com.')\n        ],\n        'validate-xml-identifier': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^[A-Z][A-Z0-9_\\/-]*$/i.test(v);\n\n            },\n            $.mage.__('Please enter a valid XML-identifier (Ex: something_1, block5, id-4).')\n        ],\n        'validate-ssn': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^\\d{3}-?\\d{2}-?\\d{4}$/.test(v);\n\n            },\n            $.mage.__('Please enter a valid social security number (Ex: 123-45-6789).')\n        ],\n        'validate-zip-us': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /(^\\d{5}$)|(^\\d{5}-\\d{4}$)/.test(v);\n\n            },\n            $.mage.__('Please enter a valid zip code (Ex: 90602 or 90602-1234).')\n        ],\n        'validate-date-au': [\n            function (v) {\n                var regex, d;\n\n                if ($.mage.isEmptyNoTrim(v)) {\n                    return true;\n                }\n                regex = /^(\\d{2})\\/(\\d{2})\\/(\\d{4})$/;\n\n                if ($.mage.isEmpty(v) || !regex.test(v)) {\n                    return false;\n                }\n                d = new Date(v.replace(regex, '$2/$1/$3'));\n\n                return parseInt(RegExp.$2, 10) === 1 + d.getMonth() &&\n                    parseInt(RegExp.$1, 10) === d.getDate() &&\n                    parseInt(RegExp.$3, 10) === d.getFullYear();\n\n            },\n            $.mage.__('Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.')\n        ],\n        'validate-currency-dollar': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^\\$?\\-?([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}\\d*(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$/.test(v); //eslint-disable-line max-len\n\n            },\n            $.mage.__('Please enter a valid $ amount. For example $100.00.')\n        ],\n        'validate-not-negative-number': [\n            function (v) {\n                if ($.mage.isEmptyNoTrim(v)) {\n                    return true;\n                }\n                v = $.mage.parseNumber(v);\n\n                return !isNaN(v) && v >= 0;\n\n            },\n            $.mage.__('Please enter a number 0 or greater in this field.')\n        ],\n        // validate-not-negative-number should be replaced in all places with this one and then removed\n        'validate-zero-or-greater': [\n            function (v) {\n                if ($.mage.isEmptyNoTrim(v)) {\n                    return true;\n                }\n                v = $.mage.parseNumber(v);\n\n                return !isNaN(v) && v >= 0;\n\n            },\n            $.mage.__('Please enter a number 0 or greater in this field.')\n        ],\n        'validate-greater-than-zero': [\n            function (v) {\n                if ($.mage.isEmptyNoTrim(v)) {\n                    return true;\n                }\n                v = $.mage.parseNumber(v);\n\n                return !isNaN(v) && v > 0;\n            },\n            $.mage.__('Please enter a number greater than 0 in this field.')\n        ],\n        'validate-css-length': [\n            function (v) {\n                if (v !== '') {\n                    return (/^[0-9]*\\.*[0-9]+(px|pc|pt|ex|em|mm|cm|in|%)?$/).test(v);\n                }\n\n                return true;\n            },\n            $.mage.__('Please input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%).')\n        ],\n        // Additional methods\n        'validate-number': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || !isNaN($.mage.parseNumber(v)) && /^\\s*-?\\d*(\\.\\d*)?\\s*$/.test(v);\n            },\n            $.mage.__('Please enter a valid number in this field.')\n        ],\n        'required-number': [\n            function (v) {\n                return !!v.length;\n            },\n            $.mage.__('Please enter a valid number in this field.')\n        ],\n        'validate-number-range': [\n            function (v, elm, param) {\n                var numValue, dataAttrRange, classNameRange, result, range, m, classes, ii;\n\n                if ($.mage.isEmptyNoTrim(v)) {\n                    return true;\n                }\n\n                numValue = $.mage.parseNumber(v);\n\n                if (isNaN(numValue)) {\n                    return false;\n                }\n\n                dataAttrRange = /^(-?[\\d.,]+)?-(-?[\\d.,]+)?$/;\n                classNameRange = /^number-range-(-?[\\d.,]+)?-(-?[\\d.,]+)?$/;\n                result = true;\n                range = param;\n\n                if (typeof range === 'string') {\n                    m = dataAttrRange.exec(range);\n\n                    if (m) {\n                        result = result && $.mage.isBetween(numValue, m[1], m[2]);\n                    } else {\n                        result = false;\n                    }\n                } else if (elm && elm.className) {\n                    classes = elm.className.split(' ');\n                    ii = classes.length;\n\n                    while (ii--) {\n                        range = classes[ii];\n                        m = classNameRange.exec(range);\n\n                        if (m) { //eslint-disable-line max-depth\n                            result = result && $.mage.isBetween(numValue, m[1], m[2]);\n                            break;\n                        }\n                    }\n                }\n\n                return result;\n            },\n            $.mage.__('The value is not within the specified range.'),\n            true\n        ],\n        'validate-digits': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || !/[^\\d]/.test(v);\n            },\n            $.mage.__('Please enter a valid number in this field.')\n        ],\n        'validate-forbidden-extensions': [\n            function (v, elem) {\n                var forbiddenExtensions = $(elem).attr('data-validation-params'),\n                    forbiddenExtensionsArray = forbiddenExtensions.split(','),\n                    extensionsArray = v.split(','),\n                    result = true;\n\n                this.validateExtensionsMessage = $.mage.__('Forbidden extensions has been used. Avoid usage of ') +\n                    forbiddenExtensions;\n\n                $.each(extensionsArray, function (key, extension) {\n                    if (forbiddenExtensionsArray.indexOf(extension) !== -1) {\n                        result = false;\n                    }\n                });\n\n                return result;\n            }, function () {\n                return this.validateExtensionsMessage;\n            }\n        ],\n        'validate-digits-range': [\n            function (v, elm, param) {\n                var numValue, dataAttrRange, classNameRange, result, range, m, classes, ii;\n\n                if ($.mage.isEmptyNoTrim(v)) {\n                    return true;\n                }\n\n                numValue = $.mage.parseNumber(v);\n\n                if (isNaN(numValue)) {\n                    return false;\n                }\n\n                dataAttrRange = /^(-?\\d+)?-(-?\\d+)?$/;\n                classNameRange = /^digits-range-(-?\\d+)?-(-?\\d+)?$/;\n                result = true;\n                range = param;\n\n                if (typeof range === 'string') {\n                    m = dataAttrRange.exec(range);\n\n                    if (m) {\n                        result = result && $.mage.isBetween(numValue, m[1], m[2]);\n                    } else {\n                        result = false;\n                    }\n                } else if (elm && elm.className) {\n                    classes = elm.className.split(' ');\n                    ii = classes.length;\n\n                    while (ii--) {\n                        range = classes[ii];\n                        m = classNameRange.exec(range);\n\n                        if (m) { //eslint-disable-line max-depth\n                            result = result && $.mage.isBetween(numValue, m[1], m[2]);\n                            break;\n                        }\n                    }\n                }\n\n                return result;\n            },\n            $.mage.__('The value is not within the specified range.'),\n            true\n        ],\n        'validate-range': [\n            function (v, elm) {\n                var minValue, maxValue, ranges, reRange, result, values,\n                    i, name, validRange, minValidRange, maxValidRange;\n\n                if ($.mage.isEmptyNoTrim(v)) {\n                    return true;\n                } else if ($.validator.methods['validate-digits'] && $.validator.methods['validate-digits'](v)) {\n                    minValue = maxValue = $.mage.parseNumber(v);\n                } else {\n                    ranges = /^(-?\\d+)?-(-?\\d+)?$/.exec(v);\n\n                    if (ranges) {\n                        minValue = $.mage.parseNumber(ranges[1]);\n                        maxValue = $.mage.parseNumber(ranges[2]);\n\n                        if (minValue > maxValue) { //eslint-disable-line max-depth\n                            return false;\n                        }\n                    } else {\n                        return false;\n                    }\n                }\n                reRange = /^range-(-?\\d+)?-(-?\\d+)?$/;\n                result = true;\n                values = $(elm).prop('class').split(' ');\n\n                for (i = values.length - 1; i >= 0; i--) {\n                    name = values[i];\n                    validRange = reRange.exec(name);\n\n                    if (validRange) {\n                        minValidRange = $.mage.parseNumber(validRange[1]);\n                        maxValidRange = $.mage.parseNumber(validRange[2]);\n                        result = result &&\n                            (isNaN(minValidRange) || minValue >= minValidRange) &&\n                            (isNaN(maxValidRange) || maxValue <= maxValidRange);\n                    }\n                }\n\n                return result;\n            },\n            $.mage.__('The value is not within the specified range.')\n        ],\n        'validate-alpha': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^[a-zA-Z]+$/.test(v);\n            },\n            $.mage.__('Please use letters only (a-z or A-Z) in this field.')\n        ],\n        'validate-code': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^[a-zA-Z]+[a-zA-Z0-9_]+$/.test(v);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.') //eslint-disable-line max-len\n        ],\n        'validate-alphanum': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^[a-zA-Z0-9]+$/.test(v);\n            },\n            $.mage.__('Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.') //eslint-disable-line max-len\n        ],\n        'validate-not-number-first': [\n            function (value) {\n                return $.mage.isEmptyNoTrim(value) || /^[^0-9-\\.].*$/.test(value.trim());\n            },\n            $.mage.__('First character must be letter.')\n        ],\n        'validate-date': [\n            function (value, params, additionalParams) {\n                var test = moment(value, utils.convertToMomentFormat(additionalParams.dateFormat));\n\n                return $.mage.isEmptyNoTrim(value) || test.isValid();\n            },\n            $.mage.__('Please enter a valid date.')\n\n        ],\n        'validate-date-range': [\n            function (v, elm) {\n                var m = /\\bdate-range-(\\w+)-(\\w+)\\b/.exec(elm.className),\n                    currentYear, normalizedTime, dependentElements;\n\n                if (!m || m[2] === 'to' || $.mage.isEmptyNoTrim(v)) {\n                    return true;\n                }\n\n                currentYear = new Date().getFullYear() + '';\n\n                /**\n                 * @param {String} vd\n                 * @return {Number}\n                 */\n                normalizedTime = function (vd) {\n                    vd = vd.split(/[.\\/]/);\n\n                    if (vd[2] && vd[2].length < 4) {\n                        vd[2] = currentYear.substr(0, vd[2].length) + vd[2];\n                    }\n\n                    return new Date(vd.join('/')).getTime();\n                };\n\n                dependentElements = $(elm.form).find('.validate-date-range.date-range-' + m[1] + '-to');\n\n                return !dependentElements.length || $.mage.isEmptyNoTrim(dependentElements[0].value) ||\n                    normalizedTime(v) <= normalizedTime(dependentElements[0].value);\n            },\n            $.mage.__('Make sure the To Date is later than or the same as the From Date.')\n        ],\n        'validate-cpassword': [\n            function () {\n                var conf = $('#confirmation').length > 0 ? $('#confirmation') : $($('.validate-cpassword')[0]),\n                    pass = false,\n                    passwordElements, i, passwordElement;\n\n                if ($('#password')) {\n                    pass = $('#password');\n                }\n                passwordElements = $('.validate-password');\n\n                for (i = 0; i < passwordElements.length; i++) {\n                    passwordElement = $(passwordElements[i]);\n\n                    if (passwordElement.closest('form').attr('id') === conf.closest('form').attr('id')) {\n                        pass = passwordElement;\n                    }\n                }\n\n                if ($('.validate-admin-password').length) {\n                    pass = $($('.validate-admin-password')[0]);\n                }\n\n                return pass.val() === conf.val();\n            },\n            $.mage.__('Please make sure your passwords match.')\n        ],\n        'validate-identifier': [\n            function (v) {\n                return $.mage.isEmptyNoTrim(v) || /^[a-z0-9][a-z0-9_\\/-]+(\\.[a-z0-9_-]+)?$/.test(v);\n            },\n            $.mage.__('Please enter a valid URL Key (Ex: \"example-page\", \"example-page.html\" or \"anotherlevel/example-page\").') //eslint-disable-line max-len\n        ],\n        'validate-zip-international': [\n\n            /*function(v) {\n             // @TODO: Cleanup\n             return Validation.get('IsEmpty').test(v) ||\n             /(^[A-z0-9]{2,10}([\\s]{0,1}|[\\-]{0,1})[A-z0-9]{2,10}$)/.test(v);\n             }*/\n            function () {\n                return true;\n            },\n            $.mage.__('Please enter a valid zip code.')\n        ],\n        'validate-one-required': [\n            function (v, elm) {\n                var p = $(elm).parent(),\n                    options = p.find('input');\n\n                return options.map(function (el) {\n                    return $(el).val();\n                }).length > 0;\n            },\n            $.mage.__('Please select one of the options above.')\n        ],\n        'validate-state': [\n            function (v) {\n                return v !== 0;\n            },\n            $.mage.__('Please select State/Province.')\n        ],\n        'required-file': [\n            function (v, elm) {\n                var result = !$.mage.isEmptyNoTrim(v),\n                    ovId;\n\n                if (!result) {\n                    ovId = $('#' + $(elm).attr('id') + '_value');\n\n                    if (ovId.length > 0) {\n                        result = !$.mage.isEmptyNoTrim(ovId.val());\n                    }\n                }\n\n                return result;\n            },\n            $.mage.__('Please select a file.')\n        ],\n        'validate-ajax-error': [\n            function (v, element) {\n                element = $(element);\n                element.on('change.ajaxError', function () {\n                    element.removeClass('validate-ajax-error');\n                    element.off('change.ajaxError');\n                });\n\n                return !element.hasClass('validate-ajax-error');\n            },\n            ''\n        ],\n        'validate-optional-datetime': [\n            function (v, elm, param) {\n                var dateTimeParts = $('.datetime-picker[id^=\"options_' + param + '\"]'),\n                    hasWithValue = false,\n                    hasWithNoValue = false,\n                    pattern = /day_part$/i,\n                    i;\n\n                for (i = 0; i < dateTimeParts.length; i++) {\n                    if (!pattern.test($(dateTimeParts[i]).attr('id'))) {\n                        if ($(dateTimeParts[i]).val() === 's') { //eslint-disable-line max-depth\n                            hasWithValue = true;\n                        } else {\n                            hasWithNoValue = true;\n                        }\n                    }\n                }\n\n                return hasWithValue ^ hasWithNoValue;\n            },\n            $.mage.__('The field isn\\'t complete.')\n        ],\n        'validate-required-datetime': [\n            function (v, elm, param) {\n                var dateTimeParts = $('.datetime-picker[id^=\"options_' + param + '\"]'),\n                    i;\n\n                for (i = 0; i < dateTimeParts.length; i++) {\n                    if (dateTimeParts[i].value === '') {\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            $.mage.__('This is a required field.')\n        ],\n        'validate-one-required-by-name': [\n            function (v, elm, selector) {\n                var name = elm.name.replace(/([\\\\\"])/g, '\\\\$1'),\n                    container = this.currentForm;\n\n                selector = selector === true ? 'input[name=\"' + name + '\"]:checked' : selector;\n\n                return !!container.querySelectorAll(selector).length;\n            },\n            $.mage.__('Please select one of the options.')\n        ],\n        'less-than-equals-to': [\n            function (value, element, params) {\n                if ($.isNumeric($(params).val()) && $.isNumeric(value)) {\n                    this.lteToVal = $(params).val();\n\n                    return parseFloat(value) <= parseFloat($(params).val());\n                }\n\n                return true;\n            },\n            function () {\n                var message = $.mage.__('Please enter a value less than or equal to %s.');\n\n                return message.replace('%s', this.lteToVal);\n            }\n        ],\n        'greater-than-equals-to': [\n            function (value, element, params) {\n                if ($.isNumeric($(params).val()) && $.isNumeric(value)) {\n                    this.gteToVal = $(params).val();\n\n                    return parseFloat(value) >= parseFloat($(params).val());\n                }\n\n                return true;\n            },\n            function () {\n                var message = $.mage.__('Please enter a value greater than or equal to %s.');\n\n                return message.replace('%s', this.gteToVal);\n            }\n        ],\n        'validate-emails': [\n            function (value) {\n                var validRegexp, emails, i;\n\n                if ($.mage.isEmpty(value)) {\n                    return true;\n                }\n                validRegexp = /^([a-z0-9,!\\#\\$%&'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z0-9,!\\#\\$%&'\\*\\+\\/=\\?\\^_`\\{\\|\\}~-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*@([a-z0-9-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z0-9-]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*\\.(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]){2,})$/i; //eslint-disable-line max-len\n                emails = value.split(/[\\s\\n\\,]+/g);\n\n                for (i = 0; i < emails.length; i++) {\n                    if (!validRegexp.test(emails[i].trim())) {\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter valid email addresses, separated by commas. For example, johndoe@domain.com, johnsmith@domain.com.') //eslint-disable-line max-len\n        ],\n\n        'validate-cc-type-select': [\n\n            /**\n             * Validate credit card type matches credit card number\n             * @param {*} value - select credit card type\n             * @param {*} element - element contains the select box for credit card types\n             * @param {*} params - selector for credit card number\n             * @return {Boolean}\n             */\n            function (value, element, params) {\n                if (value && params && creditCartTypes[value]) {\n                    return creditCartTypes[value][0].test($(params).val().replace(/\\s+/g, ''));\n                }\n\n                return false;\n            },\n            $.mage.__('Card type does not match credit card number.')\n        ],\n        'validate-cc-number': [\n\n            /**\n             * Validate credit card number based on mod 10.\n             *\n             * @param {*} value - credit card number\n             * @return {Boolean}\n             */\n            function (value) {\n                if (value) {\n                    return validateCreditCard(value);\n                }\n\n                return false;\n            },\n            $.mage.__('Please enter a valid credit card number.')\n        ],\n        'validate-cc-type': [\n\n            /**\n             * Validate credit card number is for the correct credit card type.\n             *\n             * @param {String} value - credit card number\n             * @param {*} element - element contains credit card number\n             * @param {*} params - selector for credit card type\n             * @return {Boolean}\n             */\n            function (value, element, params) {\n                var ccType;\n\n                if (value && params) {\n                    ccType = $(params).val();\n                    value = value.replace(/\\s/g, '').replace(/\\-/g, '');\n\n                    if (creditCartTypes[ccType] && creditCartTypes[ccType][0]) {\n                        return creditCartTypes[ccType][0].test(value);\n                    } else if (creditCartTypes[ccType] && !creditCartTypes[ccType][0]) {\n                        return true;\n                    }\n                }\n\n                return false;\n            },\n            $.mage.__('Credit card number does not match credit card type.')\n        ],\n        'validate-cc-exp': [\n\n            /**\n             * Validate credit card expiration date, make sure it's within the year and not before current month.\n             *\n             * @param {*} value - month\n             * @param {*} element - element contains month\n             * @param {*} params - year selector\n             * @return {Boolean}\n             */\n            function (value, element, params) {\n                var isValid = false,\n                    month, year, currentTime, currentMonth, currentYear;\n\n                if (value && params) {\n                    month = value;\n                    year = $(params).val();\n                    currentTime = new Date();\n                    currentMonth = currentTime.getMonth() + 1;\n                    currentYear = currentTime.getFullYear();\n\n                    isValid = !year || year > currentYear || year == currentYear && month >= currentMonth; //eslint-disable-line\n                }\n\n                return isValid;\n            },\n            $.mage.__('Incorrect credit card expiration date.')\n        ],\n        'validate-cc-cvn': [\n\n            /**\n             * Validate credit card cvn based on credit card type.\n             *\n             * @param {*} value - credit card cvn\n             * @param {*} element - element contains credit card cvn\n             * @param {*} params - credit card type selector\n             * @return {*}\n             */\n            function (value, element, params) {\n                var ccType;\n\n                if (value && params) {\n                    ccType = $(params).val();\n\n                    if (creditCartTypes[ccType] && creditCartTypes[ccType][0]) {\n                        return creditCartTypes[ccType][1].test(value);\n                    }\n                }\n\n                return false;\n            },\n            $.mage.__('Please enter a valid credit card verification number.')\n        ],\n        'validate-cc-ukss': [\n\n            /**\n             * Validate Switch/Solo/Maestro issue number and start date is filled.\n             *\n             * @param {*} value - input field value\n             * @return {*}\n             */\n            function (value) {\n                return value;\n            },\n            $.mage.__('Please enter issue number or start date for switch/solo card type.')\n        ],\n        'validate-length': [\n            function (v, elm) {\n                var reMax = new RegExp(/^maximum-length-[0-9]+$/),\n                    reMin = new RegExp(/^minimum-length-[0-9]+$/),\n                    validator = this,\n                    result = true,\n                    length = 0;\n\n                $.each(elm.className.split(' '), function (index, name) {\n                    if (name.match(reMax) && result) {\n                        length = name.split('-')[2];\n                        result = v.length <= length;\n                        validator.validateMessage =\n                            $.mage.__('Please enter less or equal than %1 symbols.').replace('%1', length);\n                    }\n\n                    if (name.match(reMin) && result && !$.mage.isEmpty(v)) {\n                        length = name.split('-')[2];\n                        result = v.length >= length;\n                        validator.validateMessage =\n                            $.mage.__('Please enter more or equal than %1 symbols.').replace('%1', length);\n                    }\n                });\n\n                return result;\n            }, function () {\n                return this.validateMessage;\n            }\n        ],\n        'required-entry': [\n            function (value) {\n                return !$.mage.isEmpty(value);\n            }, $.mage.__('This is a required field.')\n        ],\n        'not-negative-amount': [\n            function (v) {\n                if (v.length) {\n                    return (/^\\s*\\d+([,.]\\d+)*\\s*%?\\s*$/).test(v);\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter positive number in this field.')\n        ],\n        'validate-per-page-value-list': [\n            function (v) {\n                var isValid = true,\n                    values = v.split(','),\n                    i;\n\n                if ($.mage.isEmpty(v)) {\n                    return isValid;\n                }\n\n                for (i = 0; i < values.length; i++) {\n                    if (!/^[0-9]+$/.test(values[i])) {\n                        isValid = false;\n                    }\n                }\n\n                return isValid;\n            },\n            $.mage.__('Please enter a valid value, ex: 10,20,30')\n        ],\n        'validate-per-page-value': [\n            function (v, elm) {\n                var values;\n\n                if ($.mage.isEmpty(v)) {\n                    return false;\n                }\n                values = $('#' + elm.id + '_values').val().split(',');\n\n                return values.indexOf(v) !== -1;\n            },\n            $.mage.__('Please enter a valid value from list')\n        ],\n        'validate-new-password': [\n            function (v) {\n                if ($.validator.methods['validate-password'] && !$.validator.methods['validate-password'](v)) {\n                    return false;\n                }\n\n                if ($.mage.isEmpty(v) && v !== '') {\n                    return false;\n                }\n\n                return true;\n            },\n            $.mage.__('Please enter 6 or more characters. Leading and trailing spaces will be ignored.')\n        ],\n        'required-if-not-specified': [\n            function (value, element, params) {\n                var valid = false,\n                    alternate = $(params),\n                    alternateValue;\n\n                if (alternate.length > 0) {\n                    valid = this.check(alternate);\n                    // if valid, it may be blank, so check for that\n                    if (valid) {\n                        alternateValue = alternate.val();\n\n                        if (typeof alternateValue == 'undefined' || alternateValue.length === 0) { //eslint-disable-line\n                            valid = false;\n                        }\n                    }\n                }\n\n                if (!valid) {\n                    valid = !this.optional(element);\n                }\n\n                return valid;\n            },\n            $.mage.__('This is a required field.')\n        ],\n        'required-if-all-sku-empty-and-file-not-loaded': [\n            function (value, element, params) {\n                var valid = false,\n                    alternate = $(params.specifiedId),\n                    alternateValue;\n\n                if (alternate.length > 0) {\n                    valid = this.check(alternate);\n                    // if valid, it may be blank, so check for that\n                    if (valid) {\n                        alternateValue = alternate.val();\n\n                        if (typeof alternateValue == 'undefined' || alternateValue.length === 0) { //eslint-disable-line\n                            valid = false;\n                        }\n                    }\n                }\n\n                if (!valid) {\n                    valid = !this.optional(element);\n                }\n\n                $('input[' + params.dataSku + '=true]').each(function () {\n                    if ($(this).val() !== '') {\n                        valid = true;\n                    }\n                });\n\n                return valid;\n            },\n            $.mage.__('Please enter valid SKU key.')\n        ],\n        'required-if-specified': [\n            function (value, element, params) {\n                var valid = true,\n                    dependent = $(params),\n                    dependentValue;\n\n                if (dependent.length > 0) {\n                    valid = this.check(dependent);\n                    // if valid, it may be blank, so check for that\n                    if (valid) {\n                        dependentValue = dependent.val();\n                        valid = typeof dependentValue != 'undefined' && dependentValue.length > 0;\n                    }\n                }\n\n                if (valid) {\n                    valid = !this.optional(element);\n                } else {\n                    valid = true; // dependent was not valid, so don't even check\n                }\n\n                return valid;\n            },\n            $.mage.__('This is a required field.')\n        ],\n        'required-number-if-specified': [\n            function (value, element, params) {\n                var valid = true,\n                    dependent = $(params),\n                    depeValue;\n\n                if (dependent.length) {\n                    valid = this.check(dependent);\n\n                    if (valid) {\n                        depeValue = dependent[0].value;\n                        valid = !!(depeValue && depeValue.length);\n                    }\n                }\n\n                return valid ? !!value.length : true;\n            },\n            $.mage.__('Please enter a valid number.')\n        ],\n        'datetime-validation': [\n            function (value, element) {\n                var isValid = true;\n\n                if ($(element).val().length === 0) {\n                    isValid = false;\n                    $(element).addClass('mage-error');\n                }\n\n                return isValid;\n            },\n            $.mage.__('This is required field')\n        ],\n        'required-text-swatch-entry': [\n            tableSingleValidation,\n            $.mage.__('Admin is a required field in each row.')\n        ],\n        'required-visual-swatch-entry': [\n            tableSingleValidation,\n            $.mage.__('Admin is a required field in each row.')\n        ],\n        'required-dropdown-attribute-entry': [\n            tableSingleValidation,\n            $.mage.__('Admin is a required field in each row.')\n        ],\n        'validate-item-quantity': [\n            function (value, element, params) {\n                var validator = this,\n                    result = false,\n                    // obtain values for validation\n                    qty = $.mage.parseNumber(value),\n                    isMinAllowedValid = typeof params.minAllowed === 'undefined' ||\n                        qty >= $.mage.parseNumber(params.minAllowed),\n                    isMaxAllowedValid = typeof params.maxAllowed === 'undefined' ||\n                        qty <= $.mage.parseNumber(params.maxAllowed),\n                    isQtyIncrementsValid = typeof params.qtyIncrements === 'undefined' ||\n                        resolveModulo(qty, $.mage.parseNumber(params.qtyIncrements)) === 0.0;\n\n                result = qty > 0;\n\n                if (result === false) {\n                    validator.itemQtyErrorMessage = $.mage.__('Please enter a quantity greater than 0.');//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                result = isMinAllowedValid;\n\n                if (result === false) {\n                    validator.itemQtyErrorMessage = $.mage.__('The fewest you may purchase is %1.').replace('%1', params.minAllowed);//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                result = isMaxAllowedValid;\n\n                if (result === false) {\n                    validator.itemQtyErrorMessage = $.mage.__('The maximum you may purchase is %1.').replace('%1', params.maxAllowed);//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                result = isQtyIncrementsValid;\n\n                if (result === false) {\n                    validator.itemQtyErrorMessage = $.mage.__('You can buy this product only in quantities of %1 at a time.').replace('%1', params.qtyIncrements);//eslint-disable-line max-len\n\n                    return result;\n                }\n\n                return result;\n            }, function () {\n                return this.itemQtyErrorMessage;\n            }\n        ],\n        'password-not-equal-to-user-name': [\n            function (value, element, params) {\n                if (typeof params === 'string') {\n                    return value.toLowerCase() !== params.toLowerCase();\n                }\n\n                return true;\n            },\n            $.mage.__('The password can\\'t be the same as the email address. Create a new password and try again.')\n        ]\n    };\n\n    $.each(rules, function (i, rule) {\n        rule.unshift(i);\n        $.validator.addMethod.apply($.validator, rule);\n    });\n    $.validator.addClassRules({\n        'required-option': {\n            required: true\n        },\n        'required-options-count': {\n            required: true\n        },\n        'validate-both-passwords': {\n            'validate-cpassword': true\n        }\n    });\n    $.validator.messages = $.extend($.validator.messages, {\n        required: $.mage.__('This is a required field.'),\n        remote: $.mage.__('Please fix this field.'),\n        email: $.mage.__('Please enter a valid email address.'),\n        url: $.mage.__('Please enter a valid URL.'),\n        date: $.mage.__('Please enter a valid date.'),\n        dateISO: $.mage.__('Please enter a valid date (ISO).'),\n        number: $.mage.__('Please enter a valid number.'),\n        digits: $.mage.__('Please enter only digits.'),\n        creditcard: $.mage.__('Please enter a valid credit card number.'),\n        equalTo: $.mage.__('Please enter the same value again.'),\n        maxlength: $.validator.format($.mage.__('Please enter no more than {0} characters.')),\n        minlength: $.validator.format($.mage.__('Please enter at least {0} characters.')),\n        rangelength: $.validator.format($.mage.__('Please enter a value between {0} and {1} characters long.')),\n        range: $.validator.format($.mage.__('Please enter a value between {0} and {1}.')),\n        max: $.validator.format($.mage.__('Please enter a value less than or equal to {0}.')),\n        min: $.validator.format($.mage.__('Please enter a value greater than or equal to {0}.'))\n    });\n\n    if ($.metadata) {\n        // Setting the type as html5 to enable data-validate attribute\n        $.metadata.setType('html5');\n    }\n\n    showLabel = $.validator.prototype.showLabel;\n    $.extend(true, $.validator.prototype, {\n        /**\n         * @param {*} element\n         * @param {*} message\n         */\n        showLabel: function (element, message) {\n            var label, elem;\n\n            showLabel.call(this, element, message);\n\n            // ARIA (adding aria-invalid & aria-describedby)\n            label = this.errorsFor(element);\n            elem = $(element);\n\n            if (!label.attr('id')) {\n                label.attr('id', this.idOrName(element) + '-error');\n            }\n            elem.attr('aria-invalid', 'true')\n                .attr('aria-describedby', label.attr('id'));\n        }\n    });\n\n    /**\n     * Validate form field without instantiating validate plug-in.\n     *\n     * @param {Element|String} element - DOM element or selector\n     * @return {Boolean} validation result\n     */\n    $.validator.validateElement = function (element) {\n        var form, validator, valid, classes;\n\n        element = $(element);\n        form = element.get(0).form;\n        validator = form ? $(form).data('validator') : null;\n\n        if (validator) {\n            return validator.element(element.get(0));\n        }\n        valid = true;\n        classes = element.prop('class').split(' ');\n        $.each(classes, $.proxy(function (i, className) {\n            if (this.methods[className] && !this.methods[className](element.val(), element.get(0))) {\n                valid = false;\n\n                return valid;\n            }\n        }, this));\n\n        return valid;\n    };\n\n    originValidateDelegate = $.fn.validateDelegate;\n\n    /**\n     * @return {*}\n     */\n    $.fn.validateDelegate = function () {\n        if (!this[0].form) {\n            return this;\n        }\n\n        return originValidateDelegate.apply(this, arguments);\n    };\n\n    /**\n     * Validate single element.\n     *\n     * @param {Element} element\n     * @param {Object} config\n     * @returns {*}\n     */\n    $.validator.validateSingleElement = function (element, config) {\n        var errors = {},\n            valid = true,\n            validateConfig = {\n                errorElement: 'label',\n                ignore: '.ignore-validate',\n                hideError: false\n            },\n            form, validator, classes, elementValue;\n\n        $.extend(validateConfig, config);\n        element = $(element).not(validateConfig.ignore);\n\n        if (!element.length) {\n            return true;\n        }\n\n        form = element.get(0).form;\n        validator = form ? $(form).data('validator') : null;\n\n        if (validator) {\n            return validator.element(element.get(0));\n        }\n\n        classes = element.prop('class').split(' ');\n        validator = element.parent().data('validator') ||\n            $.mage.validation(validateConfig, element.parent()).validate;\n\n        element.removeClass(validator.settings.errorClass);\n        validator.toHide = validator.toShow;\n        validator.hideErrors();\n        validator.toShow = validator.toHide = $([]);\n\n        $.each(classes, $.proxy(function (i, className) {\n            elementValue = element.val();\n\n            if (element.is(':checkbox') || element.is(':radio')) {\n                elementValue = element.is(':checked') || null;\n            }\n\n            if (this.methods[className] && !this.methods[className](elementValue, element.get(0))) {\n                valid = false;\n                errors[element.get(0).name] = this.messages[className];\n                validator.invalid[element.get(0).name] = true;\n\n                if (!validateConfig.hideError) {\n                    validator.showErrors(errors);\n                }\n\n                return valid;\n            }\n        }, this));\n\n        return valid;\n    };\n\n    $.widget('mage.validation', {\n        options: {\n            meta: 'validate',\n            onfocusout: false,\n            onkeyup: false,\n            onclick: false,\n            ignoreTitle: true,\n            errorClass: 'mage-error',\n            errorElement: 'div',\n\n            /**\n             * @param {*} error\n             * @param {*} element\n             */\n            errorPlacement: function (error, element) {\n                var errorPlacement = element,\n                    fieldWrapper;\n\n                // logic for date-picker error placement\n                if (element.hasClass('_has-datepicker')) {\n                    errorPlacement = element.siblings('button');\n                }\n                // logic for field wrapper\n                fieldWrapper = element.closest('.addon');\n\n                if (fieldWrapper.length) {\n                    errorPlacement = fieldWrapper.after(error);\n                }\n                //logic for checkboxes/radio\n                if (element.is(':checkbox') || element.is(':radio')) {\n                    errorPlacement = element.parents('.control').children().last();\n\n                    //fallback if group does not have .control parent\n                    if (!errorPlacement.length) {\n                        errorPlacement = element.siblings('label').last();\n                    }\n                }\n                //logic for control with tooltip\n                if (element.siblings('.tooltip').length) {\n                    errorPlacement = element.siblings('.tooltip');\n                }\n                //logic for select with tooltip in after element\n                if (element.next().find('.tooltip').length) {\n                    errorPlacement = element.next();\n                }\n                errorPlacement.after(error);\n            }\n        },\n\n        /**\n         * Check if form pass validation rules without submit.\n         *\n         * @return boolean\n         */\n        isValid: function () {\n            return this.element.valid();\n        },\n\n        /**\n         * Remove validation error messages\n         */\n        clearError: function () {\n            if (arguments.length) {\n                $.each(arguments, $.proxy(function (index, item) {\n                    this.validate.prepareElement(item);\n                    this.validate.hideErrors();\n                }, this));\n            } else {\n                this.validate.resetForm();\n            }\n        },\n\n        /**\n         * Validation creation.\n         *\n         * @protected\n         */\n        _create: function () {\n            this.validate = this.element.validate(this.options);\n\n            // ARIA (adding aria-required attribute)\n            this.element\n                .find('.field.required')\n                .find('.control')\n                .find('input, select, textarea')\n                .attr('aria-required', 'true');\n            this.element\n                .find('.field.additional')\n                .find('.control')\n                .find('input, select, textarea')\n                .removeAttr('aria-required');\n            this._listenFormValidate();\n        },\n\n        /**\n         * Validation listening.\n         *\n         * @protected\n         */\n        _listenFormValidate: function () {\n            $('form').on('invalid-form.validate', this.listenFormValidateHandler);\n        },\n\n        /**\n         * Handle form validation. Focus on first invalid form field.\n         *\n         * @param {jQuery.Event} event\n         * @param {Object} validation\n         */\n        listenFormValidateHandler: function (event, validation) {\n            var firstActive = $(validation.errorList[0].element || []),\n                lastActive = $(validation.findLastActive() ||\n                    validation.errorList.length && validation.errorList[0].element || []),\n                windowHeight = $(window).height(),\n                parent, successList;\n\n            if (lastActive.is(':hidden')) {\n                parent = lastActive.parent();\n                $('html, body').animate({\n                    scrollTop: parent.offset().top - windowHeight / 2\n                });\n            }\n\n            // ARIA (removing aria attributes if success)\n            successList = validation.successList;\n\n            if (successList.length) {\n                $.each(successList, function () {\n                    $(this)\n                        .removeAttr('aria-describedby')\n                        .removeAttr('aria-invalid');\n                });\n            }\n\n            if (firstActive.length) {\n                $('html, body').stop().animate({\n                    scrollTop: firstActive.parent().offset().top - windowHeight / 2\n                });\n                firstActive.trigger('focus');\n            }\n        }\n    });\n\n    return $.mage.validation;\n});\n","mage/decorate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable strict */\ndefine([\n    'jquery',\n    'mage/translate'\n], function ($) {\n    var methods = {\n        /**\n         * Decorate a list (e.g. a <ul> containing <li>) recursively if specified.\n         * @param {Boolean} isRecursive\n         */\n        list: function (isRecursive) {\n            return this.each(function () {\n                var list = $(this),\n                    items;\n\n                if (list.length > 0) {\n                    items = typeof isRecursive === 'undefined' || isRecursive ?\n                        list.find('li') :\n                        list.children();\n                    items.decorate('generic', ['odd', 'even', 'last']);\n                }\n            });\n        },\n\n        /**\n         * Annotate a set of DOM elements with decorator classes.\n         * @param {Array} decoratorParams\n         */\n        generic: function (decoratorParams) {\n            var elements = $(this),\n                allSupportedParams;\n\n            if (elements) {\n                allSupportedParams = {\n                    even: 'odd', // Flip jQuery odd/even so that index 0 is odd.\n                    odd: 'even',\n                    last: 'last',\n                    first: 'first'\n                };\n\n                decoratorParams = decoratorParams || allSupportedParams;\n\n                $.each(decoratorParams, function (index, param) {\n                    if (param === 'even' || param === 'odd') {\n                        elements.filter(':' + param).removeClass('odd even').addClass(allSupportedParams[param]);\n                    } else {\n                        elements.filter(':' + param).addClass(allSupportedParams[param]);\n                    }\n                });\n            }\n\n            return this;\n        },\n\n        /**\n         * Decorate DOM elements in an HTML table with specified classes.\n         * @param {Object} instanceOptions\n         */\n        table: function (instanceOptions) {\n            return this.each(function () {\n                var table = $(this),\n                    options;\n\n                if (table.length > 0) {\n                    options = {\n                        'tbody': false,\n                        'tbody tr': ['odd', 'even', 'first', 'last'],\n                        'thead tr': ['first', 'last'],\n                        'tfoot tr': ['first', 'last'],\n                        'tr td': ['last']\n                    };\n\n                    $.extend(options, instanceOptions || {});\n\n                    $.each(options, function (key, value) {\n                        if (options[key]) {\n                            if (key === 'tr td') {\n                                $.each(table.find('tr'), function () {\n                                    $(this).find('td').decorate('generic', options['tr td']);\n                                });\n                            } else {\n                                table.find(key).decorate('generic', value);\n                            }\n                        }\n                    });\n                }\n            });\n        },\n\n        /**\n         * Annotate data list elements with CSS classes.\n         */\n        dataList: function () {\n            return this.each(function () {\n                var list = $(this);\n\n                if (list) {\n                    list.find('dt').decorate('generic', ['odd', 'even', 'last']);\n                    list.find('dd').decorate('generic', ['odd', 'even', 'last']);\n                }\n            });\n        }\n    };\n\n    /**\n     * @param {String} method\n     * @return {*}\n     */\n    $.fn.decorate = function (method) {\n        var message;\n\n        if (methods[method]) {\n            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));\n        } else if (typeof method === 'object' || !method) {\n            return methods.init.apply(this, arguments);\n        }\n\n        message = $.mage.__('Method %s does not exist on jQuery.decorate');\n        // eslint-disable-next-line jquery-no-event-shorthand\n        $.error(message.replace('%s', method));\n    };\n});\n","mage/dropdowns.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery'\n], function ($) {\n    'use strict';\n\n    /**\n     * @param {Object} options\n     */\n    $.fn.dropdown = function (options) {\n        var defaults = {\n                parent: null,\n                autoclose: true,\n                btnArrow: '.arrow',\n                menu: '[data-target=\"dropdown\"]',\n                activeClass: 'active'\n            },\n            actionElem = $(this),\n            self = this;\n\n        options = $.extend(defaults, options);\n        actionElem = $(this);\n        self = this;\n\n        /**\n         * @param {HTMLElement} elem\n         */\n        this.openDropdown = function (elem) {\n            elem\n                .addClass(options.activeClass)\n                .attr('aria-expanded', true)\n                .parent()\n                    .addClass(options.activeClass);\n\n            elem.parent()\n                .find(options.menu)\n                .attr('aria-hidden', false);\n\n            $(options.btnArrow, elem).text('-');\n        };\n\n        /**\n         * @param {HTMLElement} elem\n         */\n        this.closeDropdown = function (elem) {\n            elem.removeClass(options.activeClass)\n                .attr('aria-expanded', false)\n                .parent()\n                    .removeClass(options.activeClass);\n\n            elem.parent()\n                .find(options.menu)\n                .attr('aria-hidden', true);\n\n            $(options.btnArrow, elem).text('+');\n        };\n\n        /**\n         * Reset all dropdowns.\n         *\n         * @param {Object} param\n         */\n        this.reset = function (param) {\n            var params = param || {},\n                dropdowns = params.elems || actionElem;\n\n            dropdowns.each(function (index, elem) {\n                self.closeDropdown($(elem));\n            });\n        };\n\n        /* document Event bindings */\n        if (options.autoclose === true) {\n            $(document).on('click.hideDropdown', this.reset);\n            $(document).on('keyup.hideDropdown', function (e) {\n                var ESC_CODE = '27';\n\n                if (e.keyCode == ESC_CODE) { //eslint-disable-line eqeqeq\n                    self.reset();\n                }\n            });\n        }\n\n        if (options.events) {\n            $.each(options.events, function (index, event) {\n                $(document).on(event.name, event.selector, event.action);\n            });\n        }\n\n        return this.each(function () {\n            var elem = $(this),\n                parent = $(options.parent).length > 0 ? $(options.parent) : elem.parent(),\n                menu = $(options.menu, parent) || $('.dropdown-menu', parent);\n\n            // ARIA (adding aria attributes)\n            if (menu.length) {\n                elem.attr('aria-haspopup', true);\n            }\n\n            if (!elem.hasClass(options.activeClass)) {\n                elem.attr('aria-expanded', false);\n                menu.attr('aria-hidden', true);\n            } else {\n                elem.attr('aria-expanded', true);\n                menu.attr('aria-hidden', false);\n            }\n\n            if (!elem.is('a, button')) {\n                elem.attr('role', 'button');\n                elem.attr('tabindex', 0);\n            }\n\n            if (elem.attr('data-trigger-keypress-button')) {\n                elem.on('keypress', function (e) {\n                    var keyCode = e.keyCode || e.which,\n                        ENTER_CODE = 13;\n\n                    if (keyCode === ENTER_CODE) {\n                        e.preventDefault();\n                        elem.trigger('click.toggleDropdown');\n                    }\n                });\n            }\n\n            elem.on('click.toggleDropdown', function () {\n                var el = actionElem;\n\n                if (options.autoclose === true) {\n                    actionElem = $();\n                    $(document).trigger('click.hideDropdown');\n                    actionElem = el;\n                }\n\n                self[el.hasClass(options.activeClass) ? 'closeDropdown' : 'openDropdown'](elem);\n\n                return false;\n            });\n        });\n    };\n\n    return function (data, el) {\n        $(el).dropdown(data);\n    };\n});\n","mage/polyfill.js":"(function (root, doc) {\n    'use strict';\n\n    var Storage;\n\n    try {\n        if (!root.localStorage || !root.sessionStorage) {\n            throw new Error();\n        }\n\n        localStorage.setItem('storage_test', 1);\n        localStorage.removeItem('storage_test');\n    } catch (e) {\n        /**\n         * Returns a storage object to shim local or sessionStorage\n         * @param {String} type - either 'local' or 'session'\n         */\n        Storage = function (type) {\n            var data;\n\n            /**\n             * Creates a cookie\n             * @param {String} name\n             * @param {String} value\n             * @param {Integer} days\n             */\n            function createCookie(name, value, days) {\n                var date, expires;\n\n                if (days) {\n                    date = new Date();\n                    date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);\n                    expires = '; expires=' + date.toGMTString();\n                } else {\n                    expires = '';\n                }\n                doc.cookie = name + '=' + value + expires + '; path=/';\n            }\n\n            /**\n             * Reads value of a cookie\n             * @param {String} name\n             */\n            function readCookie(name) {\n                var nameEQ = name + '=',\n                    ca = doc.cookie.split(';'),\n                    i = 0,\n                    c;\n\n                for (i = 0; i < ca.length; i++) {\n                    c = ca[i];\n\n                    while (c.charAt(0) === ' ') {\n                        c = c.substring(1, c.length);\n                    }\n\n                    if (c.indexOf(nameEQ) === 0) {\n                        return c.substring(nameEQ.length, c.length);\n                    }\n                }\n\n                return null;\n            }\n\n            /**\n             * Returns cookie name based upon the storage type.\n             * If this is session storage, the function returns a unique cookie per tab\n             */\n            function getCookieName() {\n\n                if (type !== 'session') {\n                    return 'localstorage';\n                }\n\n                if (!root.name) {\n                    root.name = new Date().getTime();\n                }\n\n                return 'sessionStorage' + root.name;\n            }\n\n            /**\n             * Sets storage cookie to a data object\n             * @param {Object} dataObject\n             */\n            function setData(dataObject) {\n                data = encodeURIComponent(JSON.stringify(dataObject));\n                createCookie(getCookieName(), data, 365);\n            }\n\n            /**\n             * Clears value of cookie data\n             */\n            function clearData() {\n                createCookie(getCookieName(), '', 365);\n            }\n\n            /**\n             * @returns value of cookie data\n             */\n            function getData() {\n                var dataResponse = readCookie(getCookieName());\n\n                return dataResponse ? JSON.parse(decodeURIComponent(dataResponse)) : {};\n            }\n\n            data = getData();\n\n            return {\n                length: 0,\n\n                /**\n                 * Clears data from storage\n                 */\n                clear: function () {\n                    data = {};\n                    this.length = 0;\n                    clearData();\n                },\n\n                /**\n                 * Gets an item from storage\n                 * @param {String} key\n                 */\n                getItem: function (key) {\n                    return data[key] === undefined ? null : data[key];\n                },\n\n                /**\n                 * Gets an item by index from storage\n                 * @param {Integer} i\n                 */\n                key: function (i) {\n                    var ctr = 0,\n                        k;\n\n                    for (k in data) {\n\n                        if (data.hasOwnProperty(k)) {\n\n                            // eslint-disable-next-line max-depth\n                            if (ctr.toString() === i.toString()) {\n                                return k;\n                            }\n                            ctr++;\n                        }\n                    }\n\n                    return null;\n                },\n\n                /**\n                 * Removes an item from storage\n                 * @param {String} key\n                 */\n                removeItem: function (key) {\n                    delete data[key];\n                    this.length--;\n                    setData(data);\n                },\n\n                /**\n                 * Sets an item from storage\n                 * @param {String} key\n                 * @param {String} value\n                 */\n                setItem: function (key, value) {\n                    data[key] = value.toString();\n                    this.length++;\n                    setData(data);\n                }\n            };\n        };\n\n        root.localStorage.prototype = root.localStorage = new Storage('local');\n        root.sessionStorage.prototype = root.sessionStorage = new Storage('session');\n    }\n})(window, document);\n","mage/mage.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/apply/main'\n], function ($, mage) {\n    'use strict';\n\n    /**\n     * Main namespace for Magento extensions\n     * @type {Object}\n     */\n    $.mage = $.mage || {};\n\n    /**\n     * Plugin mage, initialize components on elements\n     * @param {String} name - Components' path.\n     * @param {Object} config - Components' config.\n     * @returns {JQuery} Chainable.\n     */\n    $.fn.mage = function (name, config) {\n        config = config || {};\n\n        this.each(function (index, el) {\n            mage.applyFor(el, config, name);\n        });\n\n        return this;\n    };\n\n    $.extend($.mage, {\n        /**\n         * Handle all components declared via data attribute\n         * @return {Object} $.mage\n         */\n        init: function () {\n            mage.apply();\n\n            return this;\n        },\n\n        /**\n         * Method handling redirects and page refresh\n         * @param {String} url - redirect URL\n         * @param {(undefined|String)} type - 'assign', 'reload', 'replace'\n         * @param {(undefined|Number)} timeout - timeout in milliseconds before processing the redirect or reload\n         * @param {(undefined|Boolean)} forced - true|false used for 'reload' only\n         */\n        redirect: function (url, type, timeout, forced) {\n            var _redirect;\n\n            forced  = !!forced;\n            timeout = timeout || 0;\n            type    = type || 'assign';\n\n            /**\n             * @private\n             */\n            _redirect = function () {\n                window.location[type](type === 'reload' ? forced : url);\n            };\n\n            timeout ? setTimeout(_redirect, timeout) : _redirect();\n        },\n\n        /**\n         * Checks if provided string is a valid selector.\n         * @param {String} selector - Selector to check.\n         * @returns {Boolean}\n         */\n        isValidSelector: function (selector) {\n            try {\n                document.querySelector(selector);\n\n                return true;\n            } catch (e) {\n                return false;\n            }\n        }\n    });\n\n    /**\n     * Init components inside of dynamically updated elements\n     */\n    $(document).on('contentUpdated', 'body', function () {\n        if (mage) {\n            mage.apply();\n        }\n    });\n\n    return $.mage;\n});\n","mage/edit-trigger.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\ndefine([\n    'jquery',\n    'mage/template',\n    'jquery-ui-modules/widget'\n], function ($, mageTemplate) {\n    'use strict';\n\n    var editTriggerPrototype;\n\n    $.widget('mage.editTrigger', {\n        options: {\n            img: '',\n            alt: '[TR]',\n            template: '#translate-inline-icon',\n            zIndex: 2000,\n            editSelector: '[data-translate]',\n            delay: 2000,\n            offsetTop: -3,\n            singleElement: true\n        },\n\n        /**\n         * editTriger creation\n         * @protected\n         */\n        _create: function () {\n            this.tmpl = mageTemplate(this.options.template);\n            this._initTrigger();\n            this._bind();\n        },\n\n        /**\n         * @return {Object}\n         * @private\n         */\n        _getCss: function () {\n            return {\n                position: 'absolute',\n                cursor: 'pointer',\n                display: 'none',\n                'z-index': this.options.zIndex\n            };\n        },\n\n        /**\n         * @param {*} appendTo\n         * @return {*|jQuery}\n         * @private\n         */\n        _createTrigger: function (appendTo) {\n            var tmpl = this.tmpl({\n                data: this.options\n            });\n\n            return $(tmpl)\n                .css(this._getCss())\n                .data('role', 'edit-trigger-element')\n                .appendTo(appendTo);\n        },\n\n        /**\n         * @private\n         */\n        _initTrigger: function () {\n            this.trigger = this._createTrigger($('body'));\n        },\n\n        /**\n         * Bind on mousemove event\n         * @protected\n         */\n        _bind: function () {\n            this.trigger.on('click.' + this.widgetName, $.proxy(this._onClick, this));\n            this.element.on('mousemove.' + this.widgetName, $.proxy(this._onMouseMove, this));\n        },\n\n        /**\n         * Show editTriger\n         */\n        show: function () {\n            if (this.trigger.is(':hidden')) {\n                this.trigger.show();\n            }\n        },\n\n        /**\n         * Hide editTriger\n         */\n        hide: function () {\n            this.currentTarget = null;\n\n            if (this.trigger && this.trigger.is(':visible')) {\n                this.trigger.hide();\n            }\n        },\n\n        /**\n         * Set editTriger position\n         * @protected\n         */\n        _setPosition: function (el) {\n            var offset = el.offset();\n\n            this.trigger.css({\n                top: offset.top + el.outerHeight() + this.options.offsetTop,\n                left: offset.left\n            });\n        },\n\n        /**\n         * Show/hide trigger on mouse move.\n         *\n         * @param {jQuery.Event} e\n         * @protected\n         */\n        _onMouseMove: function (e) {\n            var target = $(e.target),\n                inner = target.find(this.options.editSelector);\n\n            if ($(e.target).is('button') && inner.length) {\n                target = inner;\n            } else if (!target.is(this.trigger) && !target.is(this.options.editSelector)) {\n                target = target.parents(this.options.editSelector).first();\n            }\n\n            if (target.length) {\n                if (!target.is(this.trigger)) {\n                    this._setPosition(target);\n                    this.currentTarget = target;\n                }\n                this.show();\n            } else {\n                this.hide();\n            }\n        },\n\n        /**\n         * Trigger event \"edit\" on element for translate.\n         *\n         * @param {jQuery.Event} e\n         * @protected\n         */\n        _onClick: function (e) {\n            e.preventDefault();\n            e.stopImmediatePropagation();\n            $(this.currentTarget).trigger('edit.' + this.widgetName);\n            this.hide(true);\n        },\n\n        /**\n         * Destroy editTriger\n         */\n        destroy: function () {\n            this.trigger.remove();\n            this.element.off('.' + this.widgetName);\n\n            return $.Widget.prototype.destroy.call(this);\n        }\n    });\n\n    /**\n     * Extention for widget editTrigger - hide trigger with delay\n     */\n    editTriggerPrototype = $.mage.editTrigger.prototype;\n\n    $.widget('mage.editTrigger', $.extend({}, editTriggerPrototype, {\n        /**\n         * Added clear timeout on trigger show\n         */\n        show: function () {\n            editTriggerPrototype.show.apply(this, arguments);\n\n            if (this.options.delay) {\n                this._clearTimer();\n            }\n        },\n\n        /**\n         * Added setTimeout on trigger hide\n         */\n        hide: function (immediate) {\n            if (!immediate && this.options.delay) {\n                if (!this.timer) {\n                    this.timer = setTimeout($.proxy(function () {\n                        editTriggerPrototype.hide.apply(this, arguments);\n                        this._clearTimer();\n                    }, this), this.options.delay);\n                }\n            } else {\n                editTriggerPrototype.hide.apply(this, arguments);\n            }\n        },\n\n        /**\n         * Clear timer\n         * @protected\n         */\n        _clearTimer: function () {\n            if (this.timer) {\n                clearTimeout(this.timer);\n                this.timer = null;\n            }\n        }\n    }));\n\n    return $.mage.editTrigger;\n});\n","mage/bootstrap.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/apply/main',\n    'Magento_Ui/js/lib/knockout/bootstrap'\n], function ($, mage) {\n    'use strict';\n\n    $.ajaxSetup({\n        cache: false\n    });\n\n    /**\n     * Init all components defined via data-mage-init attribute.\n     * Execute in a separate task to prevent main thread blocking.\n     */\n    setTimeout(mage.apply);\n});\n","mage/url.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable strict */\ndefine([], function () {\n    var baseUrl = '';\n\n    return {\n        /**\n         * @param {String} url\n         */\n        setBaseUrl: function (url) {\n            baseUrl = url;\n        },\n\n        /**\n         * @param {String} path\n         * @return {*}\n         */\n        build: function (path) {\n            if (path.indexOf(baseUrl) !== -1) {\n                return path;\n            }\n\n            return baseUrl + path;\n        }\n    };\n});\n","mage/calendar.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/*eslint max-depth: 0*/\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget',\n    'jquery-ui-modules/datepicker',\n    'jquery-ui-modules/timepicker'\n], function ($) {\n    'use strict';\n\n    var calendarBasePrototype,\n        datepickerPrototype = $.datepicker.constructor.prototype;\n\n    $.datepicker.markerClassName = '_has-datepicker';\n\n    /**\n     * Extend JQuery date picker prototype with store local time methods\n     */\n    $.extend(datepickerPrototype, {\n        /**\n         * Get date/time according to store settings.\n         * We use serverTimezoneOffset (in seconds) instead of serverTimezoneSeconds\n         * in order to have ability to know actual store time even if page hadn't been reloaded\n         * @returns {Date}\n         */\n        _getTimezoneDate: function (options) {\n            // local time in ms\n            var ms = Date.now();\n\n            options = options || $.calendarConfig || {};\n\n            // Adjust milliseconds according to store timezone offset,\n            // mind the GMT zero offset\n            if (typeof options.serverTimezoneOffset !== 'undefined') {\n                // Make UTC time and add store timezone offset in seconds\n                ms += new Date().getTimezoneOffset() * 60 * 1000 + options.serverTimezoneOffset * 1000;\n            } else if (typeof options.serverTimezoneSeconds !== 'undefined') {\n                //Set milliseconds according to client local timezone offset\n                ms = (options.serverTimezoneSeconds + new Date().getTimezoneOffset() * 60) * 1000;\n            }\n\n            return new Date(ms);\n        },\n\n        /**\n         * Set date/time according to store settings.\n         * @param {String|Object} target - the target input field or division or span\n         */\n        _setTimezoneDateDatepicker: function (target) {\n            this._setDateDatepicker(target, this._getTimezoneDate());\n        }\n    });\n\n    /**\n     * Widget calendar\n     */\n    $.widget('mage.calendar', {\n        options: {\n            autoComplete: true\n        },\n\n        /**\n         * Merge global options with options passed to widget invoke\n         * @protected\n         */\n        _create: function () {\n            this._enableAMPM();\n            this.options = $.extend(\n                {},\n                $.calendarConfig ? $.calendarConfig : {},\n                this.options.showsTime ? {\n                    showTime: true,\n                    showHour: true,\n                    showMinute: true\n                } : {},\n                this.options\n            );\n            this._initPicker(this.element);\n            this._overwriteGenerateHtml();\n        },\n\n        /**\n         * Get picker name\n         * @protected\n         */\n        _picker: function () {\n            return this.options.showsTime ? 'datetimepicker' : 'datepicker';\n        },\n\n        /**\n         * Fix for Timepicker - Set ampm option for Timepicker if timeformat contains string 'tt'\n         * @protected\n         */\n        _enableAMPM: function () {\n            if (this.options.timeFormat && this.options.timeFormat.indexOf('tt') >= 0) {\n                this.options.ampm = true;\n            }\n        },\n\n        /**\n         * Wrapper for overwrite jQuery UI datepicker function.\n         */\n        _overwriteGenerateHtml: function () {\n            /**\n             * Overwrite jQuery UI datepicker function.\n             * Reason: magento date could be set before calendar show\n             * but local date will be styled as current in original _generateHTML\n             *\n             * @param {Object} inst - instance datepicker.\n             * @return {String} html template\n             */\n            $.datepicker.constructor.prototype._generateHTML = function (inst) {\n                var today = this._getTimezoneDate(),\n                    isRTL = this._get(inst, 'isRTL'),\n                    showButtonPanel = this._get(inst, 'showButtonPanel'),\n                    hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'),\n                    navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'),\n                    numMonths = this._getNumberOfMonths(inst),\n                    showCurrentAtPos = this._get(inst, 'showCurrentAtPos'),\n                    stepMonths = this._get(inst, 'stepMonths'),\n                    isMultiMonth = parseInt(numMonths[0], 10) !== 1 || parseInt(numMonths[1], 10) !== 1,\n                    currentDate = this._daylightSavingAdjust(!inst.currentDay ? new Date(9999, 9, 9) :\n                        new Date(inst.currentYear, inst.currentMonth, inst.currentDay)),\n                    minDate = this._getMinMaxDate(inst, 'min'),\n                    maxDate = this._getMinMaxDate(inst, 'max'),\n                    drawMonth = inst.drawMonth - showCurrentAtPos,\n                    drawYear = inst.drawYear,\n                    maxDraw,\n                    prevText = this._get(inst, 'prevText'),\n                    prev,\n                    nextText = this._get(inst, 'nextText'),\n                    next,\n                    currentText = this._get(inst, 'currentText'),\n                    gotoDate,\n                    controls,\n                    buttonPanel,\n                    firstDay,\n                    showWeek = this._get(inst, 'showWeek'),\n                    dayNames = this._get(inst, 'dayNames'),\n                    dayNamesMin = this._get(inst, 'dayNamesMin'),\n                    monthNames = this._get(inst, 'monthNames'),\n                    monthNamesShort =  this._get(inst, 'monthNamesShort'),\n                    beforeShowDay = this._get(inst, 'beforeShowDay'),\n                    showOtherMonths = this._get(inst, 'showOtherMonths'),\n                    selectOtherMonths = this._get(inst, 'selectOtherMonths'),\n                    defaultDate = this._getDefaultDate(inst),\n                    html = '',\n                    row = 0,\n                    col = 0,\n                    selectedDate,\n                    cornerClass = ' ui-corner-all',\n                    group = '',\n                    calender = '',\n                    dow = 0,\n                    thead,\n                    day,\n                    daysInMonth,\n                    leadDays,\n                    curRows,\n                    numRows,\n                    printDate,\n                    dRow = 0,\n                    tbody,\n                    daySettings,\n                    otherMonth,\n                    unselectable;\n\n                if (drawMonth < 0) {\n                    drawMonth += 12;\n                    drawYear--;\n                }\n\n                if (maxDate) {\n                    maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),\n                        maxDate.getMonth() - numMonths[0] * numMonths[1] + 1, maxDate.getDate()));\n                    maxDraw = minDate && maxDraw < minDate ? minDate : maxDraw;\n\n                    while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {\n                        drawMonth--;\n\n                        if (drawMonth < 0) {\n                            drawMonth = 11;\n                            drawYear--;\n\n                        }\n                    }\n                }\n                inst.drawMonth = drawMonth;\n                inst.drawYear = drawYear;\n                prevText = !navigationAsDateFormat ? prevText : this.formatDate(prevText,\n                    this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),\n                    this._getFormatConfig(inst));\n                prev = this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?\n                    '<a class=\"ui-datepicker-prev ui-corner-all\" data-handler=\"prev\" data-event=\"click\"' +\n                    ' title=\"' + prevText + '\">' +\n                    '<span class=\"ui-icon ui-icon-circle-triangle-' + (isRTL ? 'e' : 'w') + '\">' +\n                    '' + prevText + '</span></a>'\n                    : hideIfNoPrevNext ? ''\n                        :   '<a class=\"ui-datepicker-prev ui-corner-all ui-state-disabled\" title=\"' +\n                            '' + prevText + '\"><span class=\"ui-icon ui-icon-circle-triangle-' +\n                            '' + (isRTL ? 'e' : 'w') + '\">' + prevText + '</span></a>';\n                nextText = !navigationAsDateFormat ?\n                    nextText\n                    :   this.formatDate(nextText,\n                        this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),\n                        this._getFormatConfig(inst));\n                next = this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?\n                    '<a class=\"ui-datepicker-next ui-corner-all\" data-handler=\"next\" data-event=\"click\"' +\n                    'title=\"' + nextText + '\"><span class=\"ui-icon ui-icon-circle-triangle-' +\n                    '' + (isRTL ? 'w' : 'e') + '\">' + nextText + '</span></a>'\n                    : hideIfNoPrevNext ? ''\n                        :   '<a class=\"ui-datepicker-next ui-corner-all ui-state-disabled\" title=\"' + nextText + '\">' +\n                            '<span class=\"ui-icon ui-icon-circle-triangle-' + (isRTL ? 'w' : 'e') + '\">' + nextText +\n                            '</span></a>';\n                gotoDate = this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today;\n                currentText = !navigationAsDateFormat ? currentText :\n                    this.formatDate(currentText, gotoDate, this._getFormatConfig(inst));\n                controls = !inst.inline ?\n                    '<button type=\"button\" class=\"ui-datepicker-close ui-state-default ui-priority-primary ' +\n                    'ui-corner-all\" data-handler=\"hide\" data-event=\"click\">' +\n                    this._get(inst, 'closeText') + '</button>'\n                    : '';\n                buttonPanel = showButtonPanel ?\n                    '<div class=\"ui-datepicker-buttonpane ui-widget-content\">' + (isRTL ? controls : '') +\n                    (this._isInRange(inst, gotoDate) ? '<button type=\"button\" class=\"ui-datepicker-current ' +\n                    'ui-state-default ui-priority-secondary ui-corner-all\" data-handler=\"today\" data-event=\"click\"' +\n                    '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';\n                firstDay = parseInt(this._get(inst, 'firstDay'), 10);\n                firstDay = isNaN(firstDay) ? 0 : firstDay;\n\n                for (row = 0; row < numMonths[0]; row++) {\n                    this.maxRows = 4;\n\n                    for (col = 0; col < numMonths[1]; col++) {\n                        selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));\n\n                        calender = '';\n\n                        if (isMultiMonth) {\n                            calender += '<div class=\"ui-datepicker-group';\n\n                            if (numMonths[1] > 1) {\n                                switch (col) {\n                                    case 0: calender += ' ui-datepicker-group-first';\n                                        cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left');\n                                        break;\n\n                                    case numMonths[1] - 1: calender += ' ui-datepicker-group-last';\n                                        cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right');\n                                        break;\n\n                                    default: calender += ' ui-datepicker-group-middle'; cornerClass = '';\n                                }\n                            }\n                            calender += '\">';\n                        }\n                        calender += '<div class=\"ui-datepicker-header ' +\n                            'ui-widget-header ui-helper-clearfix' + cornerClass + '\">' +\n                            (/all|left/.test(cornerClass) && parseInt(row, 10) === 0 ? isRTL ? next : prev : '') +\n                            (/all|right/.test(cornerClass) && parseInt(row, 10) === 0 ? isRTL ? prev : next : '') +\n                            this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,\n                            row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers\n                            '</div><table class=\"ui-datepicker-calendar\"><thead>' +\n                            '<tr>';\n                        thead = showWeek ?\n                            '<th class=\"ui-datepicker-week-col\">' + this._get(inst, 'weekHeader') + '</th>' : '';\n\n                        for (dow = 0; dow < 7; dow++) { // days of the week\n                            day = (dow + firstDay) % 7;\n                            thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ?\n                                ' class=\"ui-datepicker-week-end\"' : '') + '>' +\n                                '<span title=\"' + dayNames[day] + '\">' + dayNamesMin[day] + '</span></th>';\n                        }\n                        calender += thead + '</tr></thead><tbody>';\n                        daysInMonth = this._getDaysInMonth(drawYear, drawMonth);\n\n                        if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {\n                            inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);\n                        }\n                        leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;\n                        curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate\n                        numRows = isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows;\n                        this.maxRows = numRows;\n                        printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));\n\n                        for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows\n                            calender += '<tr>';\n                            tbody = !showWeek ? '' : '<td class=\"ui-datepicker-week-col\">' +\n                            this._get(inst, 'calculateWeek')(printDate) + '</td>';\n\n                            for (dow = 0; dow < 7; dow++) { // create date picker days\n                                daySettings = beforeShowDay ?\n                                    beforeShowDay.apply(inst.input ? inst.input[0] : null, [printDate]) : [true, ''];\n                                otherMonth = printDate.getMonth() !== drawMonth;\n                                unselectable = otherMonth && !selectOtherMonths || !daySettings[0] ||\n                                minDate && printDate < minDate || maxDate && printDate > maxDate;\n                                tbody += '<td class=\"' +\n                                ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends\n                                (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months\n                                (printDate.getTime() === selectedDate.getTime() &&\n                                drawMonth === inst.selectedMonth && inst._keyEvent || // user pressed key\n                                defaultDate.getTime() === printDate.getTime() &&\n                                defaultDate.getTime() === selectedDate.getTime() ?\n                                    // or defaultDate is current printedDate and defaultDate is selectedDate\n                                ' ' + this._dayOverClass : '') + // highlight selected day\n                                (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled' : '') +\n                                (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates\n                                (printDate.getTime() === currentDate.getTime() ? ' ' + this._currentClass : '') +\n                                (printDate.getDate() === today.getDate() && printDate.getMonth() === today.getMonth() &&\n                                printDate.getYear() === today.getYear() ? ' ui-datepicker-today' : '')) + '\"' +\n                                ((!otherMonth || showOtherMonths) && daySettings[2] ?\n                                ' title=\"' + daySettings[2] + '\"' : '') + // cell title\n                                (unselectable ? '' : ' data-handler=\"selectDay\" data-event=\"click\" data-month=\"' +\n                                '' + printDate.getMonth() + '\" data-year=\"' + printDate.getFullYear() + '\"') + '>' +\n                                (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months\n                                    unselectable ? '<span class=\"ui-state-default\">' + printDate.getDate() + '</span>'\n                                        : '<a class=\"ui-state-default' +\n                                    (printDate.getTime() === today.getTime() ? ' ' : '') +\n                                    (printDate.getTime() === currentDate.getTime() ? ' ui-state-active' : '') +\n                                    (otherMonth ? ' ui-priority-secondary' : '') +\n                                    '\" data-date=\"' + printDate.getDate() + '\" href=\"#\">' +\n                                        printDate.getDate() + '</a>') + '</td>';\n                                printDate.setDate(printDate.getDate() + 1);\n                                printDate = this._daylightSavingAdjust(printDate);\n                            }\n                            calender += tbody + '</tr>';\n                        }\n                        drawMonth++;\n\n                        if (drawMonth > 11) {\n                            drawMonth = 0;\n                            drawYear++;\n                        }\n                        calender += '</tbody></table>' + (isMultiMonth ? '</div>' +\n                        (numMonths[0] > 0 && col === numMonths[1] - 1 ? '<div class=\"ui-datepicker-row-break\"></div>'\n                            : '') : '');\n                        group += calender;\n                    }\n                    html += group;\n                }\n                html += buttonPanel + ($.ui.ie6 && !inst.inline ?\n                    '<iframe src=\"javascript:false;\" class=\"ui-datepicker-cover\" frameborder=\"0\"></iframe>' : '');\n                inst._keyEvent = false;\n\n                return html;\n            };\n        },\n\n        /**\n         * Set current date if the date is not set\n         * @protected\n         * @param {Object} element\n         */\n        _setCurrentDate: function (element) {\n            if (!element.val()) {\n                element[this._picker()]('setTimezoneDate').val('');\n            }\n        },\n\n        /**\n         * Init Datetimepicker\n         * @protected\n         * @param {Object} element\n         */\n        _initPicker: function (element) {\n            var picker = element[this._picker()](this.options),\n                pickerButtonText = picker.next('.ui-datepicker-trigger')\n                    .find('img')\n                    .attr('title');\n\n            picker.next('.ui-datepicker-trigger')\n                .addClass('v-middle')\n                .text('') // Remove jQuery UI datepicker generated image\n                .append('<span>' + pickerButtonText + '</span>');\n\n            $(element).attr('autocomplete', this.options.autoComplete ? 'on' : 'off');\n\n            this._setCurrentDate(element);\n        },\n\n        /**\n         * destroy instance of datetimepicker\n         */\n        _destroy: function () {\n            this.element[this._picker()]('destroy');\n            this._super();\n        },\n\n        /**\n         * Method is kept for backward compatibility and unit-tests acceptance\n         * see \\mage\\calendar\\calendar-test.js\n         * @return {Object} date\n         */\n        getTimezoneDate: function () {\n            return datepickerPrototype._getTimezoneDate.call(this, this.options);\n        }\n    });\n\n    calendarBasePrototype = $.mage.calendar.prototype;\n\n    /**\n     * Extension for Calendar - date and time format convert functionality\n     * @var {Object}\n     */\n    $.widget('mage.calendar', $.extend({}, calendarBasePrototype,\n            /** @lends {$.mage.calendar.prototype} */ {\n                /**\n                 * key - backend format, value - jquery format\n                 * @type {Object}\n                 * @private\n                 */\n                dateTimeFormat: {\n                    date: {\n                        'EEEE': 'DD',\n                        'EEE': 'D',\n                        'EE': 'D',\n                        'E': 'D',\n                        'D': 'o',\n                        'MMMM': 'MM',\n                        'MMM': 'M',\n                        'MM': 'mm',\n                        'M': 'mm',\n                        'yyyy': 'yy',\n                        'y': 'yy',\n                        'Y': 'yy',\n                        'yy': 'yy' // Always long year format on frontend\n                    },\n                    time: {\n                        'a': 'TT'\n                    }\n                },\n\n                /**\n                 * Add Date and Time converting to _create method\n                 * @protected\n                 */\n                _create: function () {\n                    if (this.options.dateFormat) {\n                        this.options.dateFormat = this._convertFormat(this.options.dateFormat, 'date');\n                    }\n\n                    if (this.options.timeFormat) {\n                        this.options.timeFormat = this._convertFormat(this.options.timeFormat, 'time');\n                    }\n                    calendarBasePrototype._create.apply(this, arguments);\n                },\n\n                /**\n                 * Converting date or time format\n                 * @protected\n                 * @param {String} format\n                 * @param {String} type\n                 * @return {String}\n                 */\n                _convertFormat: function (format, type) {\n                    var symbols = format.match(/([a-z]+)/ig),\n                        separators = format.match(/([^a-z]+)/ig),\n                        self = this,\n                        convertedFormat = '';\n\n                    if (symbols) {\n                        $.each(symbols, function (key, val) {\n                            convertedFormat +=\n                                (self.dateTimeFormat[type][val] || val) +\n                                (separators[key] || '');\n                        });\n                    }\n\n                    return convertedFormat;\n                }\n            })\n    );\n\n    /**\n     * Widget dateRange\n     * @extends $.mage.calendar\n     */\n    $.widget('mage.dateRange', $.mage.calendar, {\n\n        /**\n         * creates two instances of datetimepicker for date range selection\n         * @protected\n         */\n        _initPicker: function () {\n            var from,\n                to;\n\n            if (this.options.from && this.options.to) {\n                from = this.element.find('#' + this.options.from.id);\n                to = this.element.find('#' + this.options.to.id);\n                this.options.onSelect = $.proxy(function (selectedDate) {\n                    to[this._picker()]('option', 'minDate', selectedDate);\n                }, this);\n                $.mage.calendar.prototype._initPicker.call(this, from);\n                from.on('change', $.proxy(function () {\n                    to[this._picker()]('option', 'minDate', from[this._picker()]('getDate'));\n                }, this));\n                this.options.onSelect = $.proxy(function (selectedDate) {\n                    from[this._picker()]('option', 'maxDate', selectedDate);\n                }, this);\n                $.mage.calendar.prototype._initPicker.call(this, to);\n                to.on('change', $.proxy(function () {\n                    from[this._picker()]('option', 'maxDate', to[this._picker()]('getDate'));\n                }, this));\n            }\n        },\n\n        /**\n         * destroy two instances of datetimepicker\n         */\n        _destroy: function () {\n            if (this.options.from) {\n                this.element.find('#' + this.options.from.id)[this._picker()]('destroy');\n            }\n\n            if (this.options.to) {\n                this.element.find('#' + this.options.to.id)[this._picker()]('destroy');\n            }\n            this._super();\n        }\n    });\n\n    // Overrides the \"today\" button functionality to select today's date when clicked.\n    $.datepicker._gotoTodayOriginal = $.datepicker._gotoToday;\n\n    /**\n     * overwrite jQuery UI _showDatepicker function for proper HTML generation conditions.\n     *\n     */\n    $.datepicker._showDatepickerOriginal = $.datepicker._showDatepicker;\n\n    /**\n     * Triggers original method showDataPicker for rendering calendar\n     * @param {HTMLObject} input\n     * @private\n     */\n    $.datepicker._showDatepicker = function (input) {\n        if (!input.disabled) {\n            $.datepicker._showDatepickerOriginal.call(this, input);\n        }\n    };\n\n    /**\n     * _gotoToday\n     * @param {Object} el\n     */\n    $.datepicker._gotoToday = function (el) {\n        //Set date/time according to timezone offset\n        $(el).datepicker('setTimezoneDate')\n            // To ensure that user can re-select date field without clicking outside it first.\n            .trigger('blur').trigger('change');\n    };\n\n    return {\n        dateRange:  $.mage.dateRange,\n        calendar:   $.mage.calendar\n    };\n});\n","mage/sticky.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.sticky', {\n        options: {\n            /**\n             * Element selector, who's height will be used to restrict the\n             * maximum offsetTop position of the stuck element.\n             * Default uses document body.\n             * @type {String}\n             */\n            container: '',\n\n            /**\n             * Spacing in pixels above the stuck element\n             * @type {Number|Function} Number or Function that will return a Number\n             */\n            spacingTop: 0,\n\n            /**\n             * Allows postponing sticking, until element will go out of the\n             * screen for the number of pixels.\n             * @type {Number|Function} Number or Function that will return a Number\n             */\n            stickAfter: 0,\n\n            /**\n             * CSS class for active sticky state\n             * @type {String}\n             */\n            stickyClass: '_sticky'\n        },\n\n        /**\n         * Retrieve option value\n         * @param  {String} option\n         * @return {*}\n         * @private\n         */\n        _getOptionValue: function (option) {\n            var value = this.options[option] || 0;\n\n            if (typeof value === 'function') {\n                value = this.options[option]();\n            }\n\n            return value;\n        },\n\n        /**\n         * Bind handlers to scroll event\n         * @private\n         */\n        _create: function () {\n            $(window).on({\n                'scroll': $.proxy(this._stick, this),\n                'resize': $.proxy(this.reset, this)\n            });\n\n            this.element.on('dimensionsChanged', $.proxy(this.reset, this));\n\n            this.reset();\n\n            // Application of the workaround for IE11 and Edge\n            this.normalizeIE11AndEdgeScroll();\n        },\n\n        /**\n         * float Block on windowScroll\n         * @private\n         */\n        _stick: function () {\n            var offset,\n                isStatic,\n                stuck,\n                stickAfter;\n\n            isStatic = this.element.css('position') === 'static';\n\n            if (!isStatic && this.element.is(':visible')) {\n                offset = $(document).scrollTop() -\n                    this.parentOffset +\n                    this._getOptionValue('spacingTop');\n\n                offset = Math.max(0, Math.min(offset, this.maxOffset));\n\n                stuck = this.element.hasClass(this.options.stickyClass);\n                stickAfter = this._getOptionValue('stickAfter');\n\n                if (offset && !stuck && offset < stickAfter) {\n                    offset = 0;\n                }\n\n                this.element\n                    .toggleClass(this.options.stickyClass, offset > 0)\n                    .css('top', offset);\n            }\n        },\n\n        /**\n         * Defines maximum offset value of the element.\n         * @private\n         */\n        _calculateDimens: function () {\n            var $parent         = this.element.parent(),\n                topMargin       = parseInt(this.element.css('margin-top'), 10),\n                parentHeight    = $parent.height() - topMargin,\n                height          = this.element.innerHeight(),\n                maxScroll       = document.body.offsetHeight - window.innerHeight;\n\n            if (this.options.container.length > 0) {\n                maxScroll = $(this.options.container).height();\n            }\n\n            this.parentOffset   = $parent.offset().top + topMargin;\n            this.maxOffset      = maxScroll - this.parentOffset;\n\n            if (this.maxOffset + height >= parentHeight) {\n                this.maxOffset = parentHeight - height;\n            }\n\n            return this;\n        },\n\n        /**\n         * Facade method that places sticky element where it should be.\n         */\n        reset: function () {\n            this._calculateDimens()\n                ._stick();\n        },\n\n        /**\n         * Workaround for IE11 and Edge that solves the IE known rendering issue\n         * that prevents sticky element from jumpy movement on scrolling the page.\n         *\n         * Alternatively, undesired jumpy movement can be eliminated by changing the setting in IE:\n         * Settings > Internet options > Advanced tab > inside 'Browsing' item > set 'Use smooth scrolling' to False\n         */\n        normalizeIE11AndEdgeScroll: function () {\n            if (navigator.userAgent.match(/Trident.*rv[ :]*11\\.|Edge\\//)) {\n                document.body.addEventListener('mousewheel', function () {\n                    event.preventDefault();\n                    window.scrollTo(0, window.pageYOffset - event.wheelDelta);\n                });\n            }\n        }\n    });\n\n    return $.mage.sticky;\n});\n","mage/translate.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/mage',\n    'mageTranslationDictionary',\n    'underscore'\n], function ($, mage, dictionary, _) {\n    'use strict';\n\n    $.extend(true, $, {\n        mage: {\n            translate: (function () {\n                /**\n                 * Key-value translations storage\n                 * @type {Object}\n                 * @private\n                 */\n                var _data = dictionary;\n\n                return {\n                    /**\n                     * Add new translation (two string parameters) or several translations (object)\n                     */\n                    add: function () {\n                        if (arguments.length > 1) {\n                            _data[arguments[0]] = arguments[1];\n                        } else if (typeof arguments[0] === 'object') {\n                            $.extend(_data, arguments[0]);\n                        }\n                    },\n\n                    /**\n                     * Make a translation with parsing (to handle case when _data represents tuple)\n                     * @param {String} text\n                     * @return {String}\n                     */\n                    translate: function (text) {\n                        return typeof _data[text] !== 'undefined' ? _data[text] : text;\n                    }\n                };\n            }())\n        }\n    });\n    $.mage.__ = $.proxy($.mage.translate.translate, $.mage.translate);\n\n    // Provide i18n wrapper to be used in underscore templates for translation\n    _.extend(_, {\n        /**\n         * Make a translation using $.mage.__\n         *\n         * @param {String} text\n         * @return {String}\n         */\n        i18n: function (text) {\n            return $.mage.__(text);\n        }\n    });\n\n    return $.mage.__;\n});\n","mage/accordion.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/tabs'\n], function ($, tabs) {\n    'use strict';\n\n    $.widget('mage.accordion', tabs, {\n        options: {\n            active: [0],\n            multipleCollapsible: false,\n            openOnFocus: false\n        },\n\n        /**\n         * @private\n         */\n        _callCollapsible: function () {\n            var self = this,\n                disabled = false,\n                active = false;\n\n            if (typeof this.options.active === 'string') {\n                this.options.active = this.options.active.split(' ').map(function (item) {\n                    return parseInt(item, 10);\n                });\n            }\n\n            $.each(this.collapsibles, function (i) {\n                disabled = active = false;\n\n                if ($.inArray(i, self.options.disabled) !== -1) {\n                    disabled = true;\n                }\n\n                if ($.inArray(i, self.options.active) !== -1) {\n                    active = true;\n                }\n                self._instantiateCollapsible(this, i, active, disabled);\n            });\n        },\n\n        /**\n         * Overwrites default functionality to provide the option to activate/deactivate multiple sections simultaneous\n         * @param {*} action\n         * @param {*} index\n         * @private\n         */\n        _toggleActivate: function (action, index) {\n            var self = this;\n\n            if (Array.isArray(index && this.options.multipleCollapsible)) {\n                $.each(index, function () {\n                    self.collapsibles.eq(this).collapsible(action);\n                });\n            } else if (index === undefined && this.options.multipleCollapsible) {\n                this.collapsibles.collapsible(action);\n            } else {\n                this._super(action, index);\n            }\n        },\n\n        /**\n         * If the Accordion allows multiple section to be active at the same time, if deep linking is used\n         * sections that don't contain the id from anchor shouldn't be closed, otherwise the accordion uses the\n         * tabs behavior\n         * @private\n         */\n        _handleDeepLinking: function () {\n            if (!this.options.multipleCollapsible) {\n                this._super();\n            }\n        },\n\n        /**\n         * Prevent default behavior that closes the other sections when one gets activated if the Accordion allows\n         * multiple sections simultaneous\n         * @private\n         */\n        _closeOthers: function () {\n            var self = this;\n\n            if (!this.options.multipleCollapsible) {\n                $.each(this.collapsibles, function () {\n                    $(this).on('beforeOpen', function () {\n                        self.collapsibles.not(this).collapsible('deactivate');\n                    });\n                });\n            }\n            $.each(this.collapsibles, function () {\n                $(this).on('beforeOpen', function () {\n                    var section = $(this);\n\n                    section.addClass('allow').prevAll().addClass('allow');\n                    section.nextAll().removeClass('allow');\n                });\n            });\n        }\n    });\n\n    return $.mage.accordion;\n});\n","mage/deletable-item.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    /**\n     * This widget is used to tag a DOM element as deletable. By default, it will use the click event on the item with a\n     * data role of delete to trigger the deletion.\n     */\n    $.widget('mage.deletableItem', {\n        options: {\n            deleteEvent: 'click',\n            deleteSelector: '[data-role=\"delete\"]',\n            hiddenClass: 'no-display'\n        },\n\n        /**\n         * This method binds elements found in this widget.\n         */\n        _bind: function () {\n            var handlers = {};\n\n            // since the first handler is dynamic, generate the object using array notation\n            handlers[this.options.deleteEvent + ' ' + this.options.deleteSelector] = '_onDeleteClicked';\n            handlers.hideDelete = '_onHideDelete';\n            handlers.showDelete = '_onShowDelete';\n\n            this._on(handlers);\n        },\n\n        /**\n         * This method constructs a new widget.\n         */\n        _create: function () {\n            this._bind();\n        },\n\n        /**\n         * This method is to initialize the control\n         * @private\n         */\n        _init: function () {\n            this._onHideDelete(); // by default, hide the control\n        },\n\n        /**\n         * This method removes the entity from the DOM.\n         * @private\n         */\n        _onDeleteClicked: function (e) {\n            e.stopPropagation();\n            this.element.trigger('deleteItem');\n        },\n\n        /**\n         * This method hides the delete capability of this item (i.e. making it not deletable)\n         * @private\n         */\n        _onHideDelete: function () {\n            this.element.find(this.options.deleteSelector).addClass(this.options.hiddenClass);\n        },\n\n        /**\n         * This method shows the delete capability of this item (i.e. making it deletable)\n         * @private\n         */\n        _onShowDelete: function () {\n            this.element.find(this.options.deleteSelector).removeClass(this.options.hiddenClass);\n        }\n    });\n\n    return $.mage.deletableItem;\n});\n","mage/cookies.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/mage',\n    'js-cookie/cookie-wrapper'\n], function ($) {\n    'use strict';\n\n    /**\n     * Helper for cookies manipulation\n     * @returns {CookieHelper}\n     * @constructor\n     */\n    var CookieHelper = function () {\n\n        /**\n         * Cookie default values.\n         * @type {Object}\n         */\n        this.defaults = {\n            expires: null,\n            path: '/',\n            domain: null,\n            secure: false,\n            lifetime: null,\n            samesite: 'lax'\n        };\n\n        /**\n         * Calculate cookie expiration date based on its lifetime.\n         * @param {Object} options - Cookie option values\n         * @return {Date|null} Calculated cookie expiration date or null if no lifetime provided.\n         * @private\n         */\n        function lifetimeToExpires(options, defaults) {\n            var expires,\n                lifetime;\n\n            lifetime = options.lifetime || defaults.lifetime;\n\n            if (lifetime && lifetime > 0) {\n                expires = options.expires || new Date();\n\n                return new Date(expires.getTime() + lifetime * 1000);\n            }\n\n            return null;\n        }\n\n        /**\n         * Set a cookie's value by cookie name based on optional cookie options.\n         * @param {String} name - The name of the cookie.\n         * @param {String} value - The cookie's value.\n         * @param {Object} options - Optional options (e.g. lifetime, expires, path, etc.)\n         */\n        this.set = function (name, value, options) {\n            var expires,\n                path,\n                domain,\n                secure,\n                samesite;\n\n            options = $.extend({}, this.defaults, options || {});\n            expires = lifetimeToExpires(options, this.defaults) || options.expires;\n            path = options.path;\n            domain = options.domain;\n            secure = options.secure;\n            samesite = options.samesite;\n\n            document.cookie = name + '=' + encodeURIComponent(value) +\n                (expires ? '; expires=' + expires.toUTCString() :  '') +\n                (path ? '; path=' + path : '') +\n                (domain ? '; domain=' + domain : '') +\n                (secure ? '; secure' : '') +\n                '; samesite=' + (samesite ? samesite : 'lax');\n        };\n\n        /**\n         * Get a cookie's value by cookie name.\n         * @param {String} name  - The name of the cookie.\n         * @return {(null|String)}\n         */\n        this.get = function (name) {\n            var arg = name + '=',\n                aLength = arg.length,\n                cookie = document.cookie,\n                cLength = cookie.length,\n                i = 0,\n                j = 0;\n\n            while (i < cLength) {\n                j = i + aLength;\n\n                if (cookie.substring(i, j) === arg) {\n                    return this.getCookieVal(j);\n                }\n                i = cookie.indexOf(' ', i) + 1;\n\n                if (i === 0) {\n                    break;\n                }\n            }\n\n            return null;\n        };\n\n        /**\n         * Clear a cookie's value by name.\n         * @param {String} name - The name of the cookie being cleared.\n         */\n        this.clear = function (name) {\n            if (this.get(name)) {\n                this.set(name, '', {\n                    expires: new Date('Jan 01 1970 00:00:01 GMT')\n                });\n            }\n        };\n\n        /**\n         * Return URI decoded cookie component value (e.g. expires, path, etc.) based on a\n         * numeric offset in the document's cookie value.\n         * @param {Number} offset - Offset into the document's cookie value.\n         * @return {String}\n         */\n        this.getCookieVal = function (offset) {\n            var cookie = document.cookie,\n                endstr = cookie.indexOf(';', offset);\n\n            if (endstr === -1) {\n                endstr = cookie.length;\n            }\n\n            return decodeURIComponent(cookie.substring(offset, endstr));\n        };\n\n        return this;\n    };\n\n    $.extend(true, $, {\n        mage: {\n            cookies: new CookieHelper()\n        }\n    });\n\n    return function (pageOptions) {\n        $.extend($.mage.cookies.defaults, pageOptions);\n        $.extend($.cookie.defaults, $.mage.cookies.defaults);\n    };\n});\n","mage/touch-slider.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'underscore',\n    'jquery-ui-modules/slider'\n], function ($, _) {\n    'use strict';\n\n    /**\n     * Adds support for touch events for regular jQuery UI slider.\n     */\n    $.widget('mage.touchSlider', $.ui.slider, {\n\n        /**\n         * Creates instance of widget.\n         *\n         * @override\n         */\n        _create: function () {\n            _.bindAll(\n                this,\n                '_mouseDown',\n                '_mouseMove',\n                '_onTouchEnd'\n            );\n\n            return this._superApply(arguments);\n        },\n\n        /**\n         * Initializes mouse events on element.\n         * @override\n         */\n        _mouseInit: function () {\n            var result = this._superApply(arguments);\n\n            this.element\n                .off('mousedown.' + this.widgetName)\n                .on('touchstart.' + this.widgetName, this._mouseDown);\n\n            return result;\n        },\n\n        /**\n         * Elements' 'mousedown' event handler polyfill.\n         * @override\n         */\n        _mouseDown: function (event) {\n            var prevDelegate = this._mouseMoveDelegate,\n                result;\n\n            event = this._touchToMouse(event);\n            result = this._super(event);\n\n            if (prevDelegate === this._mouseMoveDelegate) {\n                return result;\n            }\n\n            $(document)\n                .off('mousemove.' + this.widgetName)\n                .off('mouseup.' + this.widgetName);\n\n            $(document)\n                .on('touchmove.' + this.widgetName, this._mouseMove)\n                .on('touchend.' + this.widgetName, this._onTouchEnd)\n                .on('tochleave.' + this.widgetName, this._onTouchEnd);\n\n            return result;\n        },\n\n        /**\n         * Documents' 'mousemove' event handler polyfill.\n         *\n         * @override\n         * @param {Event} event - Touch event object.\n         */\n        _mouseMove: function (event) {\n            event = this._touchToMouse(event);\n\n            return this._super(event);\n        },\n\n        /**\n         * Documents' 'touchend' event handler.\n         */\n        _onTouchEnd: function (event) {\n            $(document).trigger('mouseup');\n\n            return this._mouseUp(event);\n        },\n\n        /**\n         * Removes previously assigned touch handlers.\n         *\n         * @override\n         */\n        _mouseUp: function () {\n            this._removeTouchHandlers();\n\n            return this._superApply(arguments);\n        },\n\n        /**\n         * Removes previously assigned touch handlers.\n         *\n         * @override\n         */\n        _mouseDestroy: function () {\n            this._removeTouchHandlers();\n\n            return this._superApply(arguments);\n        },\n\n        /**\n         * Removes touch events from document object.\n         */\n        _removeTouchHandlers: function () {\n            $(document)\n                .off('touchmove.' + this.widgetName)\n                .off('touchend.' + this.widgetName)\n                .off('touchleave.' + this.widgetName);\n        },\n\n        /**\n         * Adds properties to the touch event to mimic mouse event.\n         *\n         * @param {Event} event - Touch event object.\n         * @returns {Event}\n         */\n        _touchToMouse: function (event) {\n            var orig = event.originalEvent,\n                touch = orig.touches[0];\n\n            return _.extend(event, {\n                which:      1,\n                pageX:      touch.pageX,\n                pageY:      touch.pageY,\n                clientX:    touch.clientX,\n                clientY:    touch.clientY,\n                screenX:    touch.screenX,\n                screenY:    touch.screenY\n            });\n        }\n    });\n\n    return $.mage.touchSlider;\n});\n","mage/smart-keyboard-handler.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery'\n], function ($) {\n    'use strict';\n\n    /**\n     * @return {Object}\n     * @constructor\n     */\n    function KeyboardHandler() {\n        var body = $('body'),\n            focusState = false,\n            tabFocusClass = '_keyfocus',\n            productsGrid = '[data-container=\"product-grid\"]',\n            catalogProductsGrid = $(productsGrid),\n            CODE_TAB = 9;\n\n        /**\n         * Handle logic, when onTabKeyPress fired at first.\n         * Then it changes state.\n         */\n        function onFocusInHandler() {\n            focusState = true;\n            body.addClass(tabFocusClass)\n                .off('focusin.keyboardHandler', onFocusInHandler);\n        }\n\n        /**\n         * Handle logic to remove state after onTabKeyPress to normal.\n         */\n        function onClickHandler() {\n            focusState = false;\n            body.removeClass(tabFocusClass)\n                .off('click', onClickHandler);\n        }\n\n        /**\n         * Tab key onKeypress handler. Apply main logic:\n         *  - call differ actions onTabKeyPress and onClick\n         */\n        function smartKeyboardFocus() {\n            $(document).on('keydown keypress', function (event) {\n                if (event.which === CODE_TAB && !focusState) {\n                    body\n                        .on('focusin.keyboardHandler', onFocusInHandler)\n                        .on('click', onClickHandler);\n                }\n            });\n\n            // ARIA support for catalog grid products\n            if (catalogProductsGrid.length) {\n                body.on('focusin.gridProducts', productsGrid, function () {\n                    if (body.hasClass(tabFocusClass)) {\n                        $(this).addClass('active');\n                    }\n                });\n                body.on('focusout.gridProducts', productsGrid, function () {\n                    $(this).removeClass('active');\n                });\n            }\n        }\n\n        /**\n         * Attach smart focus on specific element.\n         * @param {jQuery} element\n         */\n        function handleFocus(element) {\n            element.on('focusin.emulateTabFocus', function () {\n                focusState = true;\n                body.addClass(tabFocusClass);\n                element.off();\n            });\n\n            element.on('focusout.emulateTabFocus', function () {\n                focusState = false;\n                body.removeClass(tabFocusClass);\n                element.off();\n            });\n        }\n\n        return {\n            apply: smartKeyboardFocus,\n            focus: handleFocus\n        };\n    }\n\n    return new KeyboardHandler;\n});\n","mage/template.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    /**\n     * Checks if provided string is a valid DOM selector.\n     *\n     * @param {String} selector - Selector to be checked.\n     * @returns {Boolean}\n     */\n    function isSelector(selector) {\n        try {\n            document.querySelector(selector);\n\n            return true;\n        } catch (e) {\n            return false;\n        }\n    }\n\n    /**\n     * Unescapes characters used in underscore templates.\n     *\n     * @param {String} str - String to be processed.\n     * @returns {String}\n     */\n    function unescape(str) {\n        return str.replace(/&lt;%|%3C%/g, '<%').replace(/%&gt;|%%3E/g, '%>');\n    }\n\n    /**\n     * If 'tmpl' is a valid selector, returns target node's innerHTML if found.\n     * Else, returns empty string and emits console warning.\n     * If 'tmpl' is not a selector, returns 'tmpl' as is.\n     *\n     * @param {String} tmpl\n     * @returns {String}\n     */\n    function getTmplString(tmpl) {\n        if (isSelector(tmpl)) {\n            tmpl = document.querySelector(tmpl);\n\n            if (tmpl) {\n                tmpl = tmpl.innerHTML.trim();\n            } else {\n                console.warn('No template was found by selector: ' + tmpl);\n\n                tmpl = '';\n            }\n        }\n\n        return unescape(tmpl);\n    }\n\n    /**\n     * Compiles or renders template provided either\n     * by selector or by the template string.\n     *\n     * @param {String} tmpl - Template string or selector.\n     * @param {(Object|Array|Function)} [data] - Data object with which to render template.\n     * @returns {String|Function}\n     */\n    return function (tmpl, data) {\n        var render;\n\n        tmpl   = getTmplString(tmpl);\n        render = _.template(tmpl);\n\n        return !_.isUndefined(data) ?\n            render(data) :\n            render;\n    };\n});\n","mage/common.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'domReady!'\n], function ($) {\n    'use strict';\n\n    /* Form with auto submit feature */\n    $('form[data-auto-submit=\"true\"]').trigger('submit');\n\n    //Add form keys.\n    $(document).on(\n        'submit',\n        'form',\n        function (e) {\n            var formKeyElement,\n                existingFormKeyElement,\n                isKeyPresentInForm,\n                isActionExternal,\n                baseUrl = window.BASE_URL,\n                form = $(e.target),\n                formKey = $('input[name=\"form_key\"]').val(),\n                formMethod = form.prop('method'),\n                formAction = form.prop('action');\n\n            isActionExternal = formAction.indexOf(baseUrl) !== 0;\n\n            existingFormKeyElement = form.find('input[name=\"form_key\"]');\n            isKeyPresentInForm = existingFormKeyElement.length;\n\n            /* Verifies that existing auto-added form key is a direct form child element,\n               protection from a case when one form contains another form. */\n            if (isKeyPresentInForm && existingFormKeyElement.attr('auto-added-form-key') === '1') {\n                isKeyPresentInForm = form.find('> input[name=\"form_key\"]').length;\n            }\n\n            if (formKey && !isKeyPresentInForm && !isActionExternal && formMethod !== 'get') {\n                formKeyElement = document.createElement('input');\n                formKeyElement.setAttribute('type', 'hidden');\n                formKeyElement.setAttribute('name', 'form_key');\n                formKeyElement.setAttribute('value', formKey);\n                formKeyElement.setAttribute('auto-added-form-key', '1');\n                form.get(0).appendChild(formKeyElement);\n            }\n        }\n    );\n});\n","mage/popup-window.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.popupWindow', {\n        options: {\n            centerBrowser: 0, // center window over browser window? {1 (YES) or 0 (NO)}. overrides top and left\n            centerScreen: 0, // center window over entire screen? {1 (YES) or 0 (NO)}. overrides top and left\n            height: 500, // sets the height in pixels of the window.\n            left: 0, // left position when the window appears.\n            location: 0, // determines whether the address bar is displayed {1 (YES) or 0 (NO)}.\n            menubar: 0, // determines whether the menu bar is displayed {1 (YES) or 0 (NO)}.\n            resizable: 0, // whether the window can be resized {1 (YES) or 0 (NO)}.\n            scrollbars: 0, // determines whether scrollbars appear on the window {1 (YES) or 0 (NO)}.\n            status: 0, // whether a status line appears at the bottom of the window {1 (YES) or 0 (NO)}.\n            width: 500, // sets the width in pixels of the window.\n            windowName: null, // name of window set from the name attribute of the element that invokes the click\n            windowURL: null, // url used for the popup\n            top: 0, // top position when the window appears.\n            toolbar: 0 // determines whether a toolbar is displayed {1 (YES) or 0 (NO)}.\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            this.element.on('click', $.proxy(this._openPopupWindow, this));\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _openPopupWindow: function (event) {\n            var element = $(event.target),\n                settings = this.options,\n                windowFeatures =\n                    'height=' + settings.height +\n                        ',width=' + settings.width +\n                        ',toolbar=' + settings.toolbar +\n                        ',scrollbars=' + settings.scrollbars +\n                        ',status=' + settings.status +\n                        ',resizable=' + settings.resizable +\n                        ',location=' + settings.location +\n                        ',menuBar=' + settings.menubar,\n                centeredX,\n                centeredY;\n\n            settings.windowName = settings.windowName || element.attr('name');\n            settings.windowURL = settings.windowURL || element.attr('href');\n\n            if (settings.centerBrowser) {\n                centeredY = window.screenY + (window.outerHeight / 2 - settings.height / 2);\n                centeredX = window.screenX + (window.outerWidth / 2 - settings.width / 2);\n                windowFeatures += ',left=' + centeredX + ',top=' + centeredY;\n            } else if (settings.centerScreen) {\n                centeredY = (screen.height - settings.height) / 2;\n                centeredX = (screen.width - settings.width) / 2;\n                windowFeatures += ',left=' + centeredX + ',top=' + centeredY;\n            } else {\n                windowFeatures += ',left=' + settings.left + ',top=' + settings.top;\n            }\n\n            window.open(settings.windowURL, settings.windowName, windowFeatures).focus();\n            event.preventDefault();\n        }\n    });\n\n    return $.mage.popupWindow;\n});\n","mage/storage.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['jquery', 'mage/url'], function ($, urlBuilder) {\n    'use strict';\n\n    return {\n        /**\n         * Perform asynchronous GET request to server.\n         * @param {String} url\n         * @param {Boolean} global\n         * @param {String} contentType\n         * @param {Object} headers\n         * @returns {Deferred}\n         */\n        get: function (url, global, contentType, headers) {\n            headers = headers || {};\n            global = global === undefined ? true : global;\n            contentType = contentType || 'application/json';\n\n            return $.ajax({\n                url: urlBuilder.build(url),\n                type: 'GET',\n                global: global,\n                contentType: contentType,\n                headers: headers\n            });\n        },\n\n        /**\n         * Perform asynchronous POST request to server.\n         * @param {String} url\n         * @param {String} data\n         * @param {Boolean} global\n         * @param {String} contentType\n         * @param {Object} headers\n         * @param {Boolean} async\n         * @returns {Deferred}\n         */\n        post: function (url, data, global, contentType, headers, async) {\n            headers = headers || {};\n            global = global === undefined ? true : global;\n            contentType = contentType || 'application/json';\n            async = async === undefined ? true : async;\n\n            return $.ajax({\n                url: urlBuilder.build(url),\n                type: 'POST',\n                data: data,\n                global: global,\n                contentType: contentType,\n                headers: headers,\n                async: async\n            });\n        },\n\n        /**\n         * Perform asynchronous PUT request to server.\n         * @param {String} url\n         * @param {String} data\n         * @param {Boolean} global\n         * @param {String} contentType\n         * @param {Object} headers\n         * @returns {Deferred}\n         */\n        put: function (url, data, global, contentType, headers) {\n            var ajaxSettings = {};\n\n            headers = headers || {};\n            global = global === undefined ? true : global;\n            contentType = contentType || 'application/json';\n            ajaxSettings.url = urlBuilder.build(url);\n            ajaxSettings.type = 'PUT';\n            ajaxSettings.data = data;\n            ajaxSettings.global = global;\n            ajaxSettings.contentType = contentType;\n            ajaxSettings.headers = headers;\n\n            return $.ajax(ajaxSettings);\n        },\n\n        /**\n         * Perform asynchronous DELETE request to server.\n         * @param {String} url\n         * @param {Boolean} global\n         * @param {String} contentType\n         * @param {Object} headers\n         * @returns {Deferred}\n         */\n        delete: function (url, global, contentType, headers) {\n            headers = headers || {};\n            global = global === undefined ? true : global;\n            contentType = contentType || 'application/json';\n\n            return $.ajax({\n                url: urlBuilder.build(url),\n                type: 'DELETE',\n                global: global,\n                contentType: contentType,\n                headers: headers\n            });\n        }\n    };\n});\n","mage/item-table.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\ndefine([\n    'jquery',\n    'mage/template',\n    'jquery-ui-modules/widget'\n], function ($, mageTemplate) {\n    'use strict';\n\n    $.widget('mage.itemTable', {\n        options: {\n            addBlock: '[data-template=\"add-block\"]',\n            addBlockData: {},\n            addEvent: 'click',\n            addSelector: '[data-role=\"add\"]',\n            itemsSelector: '[data-container=\"items\"]',\n            keepLastRow: true\n        },\n\n        /**\n         * This method adds a new instance of the block to the items.\n         * @private\n         */\n        _add: function () {\n            var hideShowDelete,\n                deletableItems,\n                addedBlock;\n\n            // adding a new row, so increment the count to give each row a unique index\n            this.rowIndex++;\n\n            // make sure the block data has the rowIndex\n            this.options.addBlockData.rowIndex = this.rowIndex;\n\n            // render the form\n            addedBlock = $(this.addBlockTmpl({\n                data: this.options.addBlockData\n            }));\n\n            // add the row to the item block\n            this.element.find(this.options.itemsSelector).append(addedBlock);\n\n            // initialize all mage content\n            addedBlock.trigger('contentUpdated');\n\n            // determine all existing items in the collection\n            deletableItems = this._getDeletableItems();\n\n            // for the most part, show the delete mechanism, except in the case where there is only one it should not\n            // be deleted\n            hideShowDelete = 'showDelete';\n\n            if (this.options.keepLastRow && deletableItems.length === 1) {\n                hideShowDelete = 'hideDelete';\n            }\n\n            // loop through each control and perform that action on the deletable item\n            $.each(deletableItems, function (index) {\n                $(deletableItems[index]).trigger(hideShowDelete);\n            });\n        },\n\n        /**\n         * This method binds elements found in this widget.\n         * @private\n         */\n        _bind: function () {\n            var handlers = {};\n\n            // since the first handler is dynamic, generate the object using array notation\n            handlers[this.options.addEvent + ' ' + this.options.addSelector] = '_add';\n            handlers.deleteItem = '_onDeleteItem';\n\n            this._on(handlers);\n        },\n\n        /**\n         * This method constructs a new widget.\n         * @private\n         */\n        _create: function () {\n            this._bind();\n\n            this.addBlockTmpl = mageTemplate(this.options.addBlock);\n\n            // nothing in the table, so indicate that\n            this.rowIndex = -1;\n\n            // make sure the block data is an object\n            if (this.options.addBlockData == null || typeof this.options.addBlockData !== 'object') {\n                // reset the block data to an empty object\n                this.options.addBlockData = {};\n            }\n\n            // add the first row to the table\n            this._add();\n        },\n\n        /**\n         * This method returns the list of widgets associated with deletable items from the container (direct children\n         * only).\n         * @private\n         */\n        _getDeletableItems: function () {\n            return this.element.find(this.options.itemsSelector + '> .deletableItem');\n        },\n\n        /**\n         * This method removes the item associated with the message.\n         * @private\n         */\n        _onDeleteItem: function (e) {\n            var deletableItems;\n\n            // parent elements don't need to see this event\n            e.stopPropagation();\n\n            // remove the deletable item\n            $(e.target).remove();\n\n            if (this.options.keepLastRow) {\n                // determine if there is only one element remaining, in which case, disable the delete mechanism on it\n                deletableItems = this._getDeletableItems();\n\n                if (deletableItems.length === 1) {\n                    $(deletableItems[0]).trigger('hideDelete');\n                }\n            }\n        }\n    });\n\n    return $.mage.itemTable;\n});\n","mage/menu.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'matchMedia',\n    'jquery-ui-modules/menu',\n    'mage/translate'\n], function ($, mediaCheck) {\n    'use strict';\n\n    /**\n     * Menu Widget - this widget is a wrapper for the jQuery UI Menu\n     */\n    $.widget('mage.menu', $.ui.menu, {\n        options: {\n            categoryLayoutClass: 'catalog-product-view',\n            responsive: false,\n            expanded: false,\n            showDelay: 42,\n            hideDelay: 300,\n            delay: 0,\n            mediaBreakpoint: '(max-width: 768px)'\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            var self = this;\n\n            this.delay = this.options.delay;\n\n            this._super();\n            $(window).on('resize', function () {\n                self.element.find('.submenu-reverse').removeClass('submenu-reverse');\n            });\n        },\n\n        /**\n         * @private\n         */\n        _init: function () {\n            this._super();\n\n            if (this.options.expanded === true) {\n                this.isExpanded();\n            }\n\n            if (this.options.responsive === true) {\n                mediaCheck({\n                    media: this.options.mediaBreakpoint,\n                    entry: $.proxy(function () {\n                        this._toggleMobileMode();\n                    }, this),\n                    exit: $.proxy(function () {\n                        this._toggleDesktopMode();\n                    }, this)\n                });\n            }\n\n            this._assignControls()._listen();\n            this._setActiveMenu();\n        },\n\n        /**\n         * @return {Object}\n         * @private\n         */\n        _assignControls: function () {\n            this.controls = {\n                toggleBtn: $('[data-action=\"toggle-nav\"]')\n            };\n\n            return this;\n        },\n\n        /**\n         * @private\n         */\n        _listen: function () {\n            var controls = this.controls,\n                toggle = this.toggle;\n\n            controls.toggleBtn.off('click');\n            controls.toggleBtn.on('click', toggle.bind(this));\n        },\n\n        /**\n         * Toggle.\n         */\n        toggle: function () {\n            var html = $('html');\n\n            if (html.hasClass('nav-open')) {\n                html.removeClass('nav-open');\n                setTimeout(function () {\n                    html.removeClass('nav-before-open');\n                }, this.options.hideDelay);\n            } else {\n                html.addClass('nav-before-open');\n                setTimeout(function () {\n                    html.addClass('nav-open');\n                }, this.options.showDelay);\n            }\n        },\n\n        /**\n         * Tries to figure out the active category for current page and add appropriate classes:\n         *  - 'active' class for active category\n         *  - 'has-active' class for all parents of active category\n         *\n         *  First, checks whether current URL is URL of category page,\n         *  otherwise tries to retrieve category URL in case of current URL is product view page URL\n         *  which has category tree path in it.\n         *\n         * @return void\n         * @private\n         */\n        _setActiveMenu: function () {\n            var currentUrl = window.location.href.split('?')[0];\n\n            if (!this._setActiveMenuForCategory(currentUrl)) {\n                this._setActiveMenuForProduct(currentUrl);\n            }\n        },\n\n        /**\n         * Looks for category with provided URL and adds 'active' CSS class to it if it was not set before.\n         * If menu item has parent categories, sets 'has-active' class to all af them.\n         *\n         * @param {String} url - possible category URL\n         * @returns {Boolean} - true if active category was founded by provided URL, otherwise return false\n         * @private\n         */\n        _setActiveMenuForCategory: function (url) {\n            var activeCategoryLink = this.element.find('a[href=\"' + url + '\"]'),\n                classes,\n                classNav;\n\n            if (!activeCategoryLink || !activeCategoryLink.hasClass('ui-menu-item-wrapper')) {\n\n                //category was not found by provided URL\n                return false;\n            } else if (!activeCategoryLink.parent().hasClass('active')) {\n                activeCategoryLink.parent().addClass('active');\n                classes = activeCategoryLink.parent().attr('class');\n                classNav = classes.match(/(nav\\-)[0-9]+(\\-[0-9]+)+/gi);\n\n                if (classNav) {\n                    this._setActiveParent(classNav[0]);\n                }\n            }\n\n            return true;\n        },\n\n        /**\n         * Sets 'has-active' CSS class to all parent categories which have part of provided class in childClassName\n         *\n         * @example\n         *  childClassName - 'nav-1-2-3'\n         *  CSS class 'has-active' will be added to categories have 'nav-1-2' and 'nav-1' classes\n         *\n         * @param {String} childClassName - Class name of active category <li> element\n         * @return void\n         * @private\n         */\n        _setActiveParent: function (childClassName) {\n            var parentElement,\n                parentClass = childClassName.substr(0, childClassName.lastIndexOf('-'));\n\n            if (parentClass.lastIndexOf('-') !== -1) {\n                parentElement = this.element.find('.' + parentClass);\n\n                if (parentElement) {\n                    parentElement.addClass('has-active');\n                }\n                this._setActiveParent(parentClass);\n            }\n        },\n\n        /**\n         * Extracts the URL extension from the given URL.\n         * It identifies the last segment of the URL after the last slash ('/') and returns the substring after the last dot ('.')\n         * If there's no dot in the last segment, it returns an empty string.\n         *\n         * @param {String} url - The URL from which to extract the extension.\n         * @return {String} The extracted URL extension or an empty string if no extension is found.\n         * @private\n         */\n        _getUrlExtension: function (url) {\n            var lastSegment = url.slice(url.lastIndexOf('/') + 1);\n            return lastSegment.includes('.') ? lastSegment.slice(lastSegment.lastIndexOf('.')) : '';\n        },\n\n        /**\n         * Determines if the current page is a product page.\n         * It checks the catalog product view related class in the body tag of the document.\n         *\n         * @return {Boolean} True if the current page is a product page, false otherwise.\n         * @private\n         */\n        _isProductPage: function () {\n            return document.body.classList.contains(this.options.categoryLayoutClass);\n        },\n\n        /**\n         * Sets the active state in the menu for a product page. Determines the category URL from either\n         * the referrer URL or the current URL, using the URL extension to identify the category.\n         * Sets the corresponding category as active in the menu if a valid category URL is found.\n         * Clears the active state if no valid category URL is found or if it's not a product page.\n         *\n         * @param {String} currentUrl - The current page URL without parameters.\n         * @return void\n         * @private\n         */\n        _setActiveMenuForProduct: function (currentUrl) {\n            var firstCategoryUrl = this.element.find('> li a').attr('href');\n\n            if (!firstCategoryUrl) {\n                this._clearActiveState();\n                return;\n            }\n\n            var categoryUrlExtension = this._getUrlExtension(firstCategoryUrl);\n            var categoryUrl;\n            var isProductPage = this._isProductPage();\n\n            if (isProductPage) {\n                var currentHostname = window.location.hostname;\n\n                if (document.referrer.includes(currentHostname) && document.referrer.endsWith(categoryUrlExtension)) {\n                    categoryUrl = document.referrer.split('?')[0];\n                } else {\n                    categoryUrl = currentUrl.substring(0, currentUrl.lastIndexOf('/')) + categoryUrlExtension;\n                }\n\n                this._setActiveMenuForCategory(categoryUrl);\n            } else {\n                this._clearActiveState();\n            }\n        },\n\n        /**\n         * Clears the active state from all menu items within the navigation element.\n         * It removes 'active' and 'has-active' classes from all list items (li elements),\n         * which are used to indicate the currently selected or parent of a selected item.\n         *\n         * @return void\n         * @private\n         */\n        _clearActiveState: function () {\n            this.element.find('li').removeClass('active has-active');\n        },\n\n        /**\n         * Add class for expanded option.\n         */\n        isExpanded: function () {\n            var subMenus = this.element.find(this.options.menus),\n                expandedMenus = subMenus.find(this.options.menus);\n\n            expandedMenus.addClass('expanded');\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _activate: function (event) {\n            window.location.href = this.active.find('> a').attr('href');\n            this.collapseAll(event);\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _keydown: function (event) {\n            var match, prev, character, skip, regex,\n                preventDefault = true;\n\n            /* eslint-disable max-depth */\n            /**\n             * @param {String} value\n             */\n            function escape(value) {\n                return value.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&');\n            }\n\n            if (this.active.closest(this.options.menus).attr('aria-expanded') != 'true') { //eslint-disable-line eqeqeq\n\n                switch (event.keyCode) {\n                    case $.ui.keyCode.PAGE_UP:\n                        this.previousPage(event);\n                        break;\n\n                    case $.ui.keyCode.PAGE_DOWN:\n                        this.nextPage(event);\n                        break;\n\n                    case $.ui.keyCode.HOME:\n                        this._move('first', 'first', event);\n                        break;\n\n                    case $.ui.keyCode.END:\n                        this._move('last', 'last', event);\n                        break;\n\n                    case $.ui.keyCode.UP:\n                        this.previous(event);\n                        break;\n\n                    case $.ui.keyCode.DOWN:\n                        if (this.active && !this.active.is('.ui-state-disabled')) {\n                            this.expand(event);\n                        }\n                        break;\n\n                    case $.ui.keyCode.LEFT:\n                        this.previous(event);\n                        break;\n\n                    case $.ui.keyCode.RIGHT:\n                        this.next(event);\n                        break;\n\n                    case $.ui.keyCode.ENTER:\n                    case $.ui.keyCode.SPACE:\n                        this._activate(event);\n                        break;\n\n                    case $.ui.keyCode.ESCAPE:\n                        this.collapse(event);\n                        break;\n                    default:\n                        preventDefault = false;\n                        prev = this.previousFilter || '';\n                        character = String.fromCharCode(event.keyCode);\n                        skip = false;\n\n                        clearTimeout(this.filterTimer);\n\n                        if (character === prev) {\n                            skip = true;\n                        } else {\n                            character = prev + character;\n                        }\n\n                        regex = new RegExp('^' + escape(character), 'i');\n                        match = this.activeMenu.children('.ui-menu-item').filter(function () {\n                            return regex.test($(this).children('a').text());\n                        });\n                        match = skip && match.index(this.active.next()) !== -1 ?\n                            this.active.nextAll('.ui-menu-item') :\n                            match;\n\n                        // If no matches on the current filter, reset to the last character pressed\n                        // to move down the menu to the first item that starts with that character\n                        if (!match.length) {\n                            character = String.fromCharCode(event.keyCode);\n                            regex = new RegExp('^' + escape(character), 'i');\n                            match = this.activeMenu.children('.ui-menu-item').filter(function () {\n                                return regex.test($(this).children('a').text());\n                            });\n                        }\n\n                        if (match.length) {\n                            this.focus(event, match);\n\n                            if (match.length > 1) {\n                                this.previousFilter = character;\n                                this.filterTimer = this._delay(function () {\n                                    delete this.previousFilter;\n                                }, 1000);\n                            } else {\n                                delete this.previousFilter;\n                            }\n                        } else {\n                            delete this.previousFilter;\n                        }\n                }\n            } else {\n                switch (event.keyCode) {\n                    case $.ui.keyCode.DOWN:\n                        this.next(event);\n                        break;\n\n                    case $.ui.keyCode.UP:\n                        this.previous(event);\n                        break;\n\n                    case $.ui.keyCode.RIGHT:\n                        if (this.active && !this.active.is('.ui-state-disabled')) {\n                            this.expand(event);\n                        }\n                        break;\n\n                    case $.ui.keyCode.ENTER:\n                    case $.ui.keyCode.SPACE:\n                        this._activate(event);\n                        break;\n\n                    case $.ui.keyCode.LEFT:\n                    case $.ui.keyCode.ESCAPE:\n                        this.collapse(event);\n                        break;\n                    default:\n                        preventDefault = false;\n                        prev = this.previousFilter || '';\n                        character = String.fromCharCode(event.keyCode);\n                        skip = false;\n\n                        clearTimeout(this.filterTimer);\n\n                        if (character === prev) {\n                            skip = true;\n                        } else {\n                            character = prev + character;\n                        }\n\n                        regex = new RegExp('^' + escape(character), 'i');\n                        match = this.activeMenu.children('.ui-menu-item').filter(function () {\n                            return regex.test($(this).children('a').text());\n                        });\n                        match = skip && match.index(this.active.next()) !== -1 ?\n                            this.active.nextAll('.ui-menu-item') :\n                            match;\n\n                        // If no matches on the current filter, reset to the last character pressed\n                        // to move down the menu to the first item that starts with that character\n                        if (!match.length) {\n                            character = String.fromCharCode(event.keyCode);\n                            regex = new RegExp('^' + escape(character), 'i');\n                            match = this.activeMenu.children('.ui-menu-item').filter(function () {\n                                return regex.test($(this).children('a').text());\n                            });\n                        }\n\n                        if (match.length) {\n                            this.focus(event, match);\n\n                            if (match.length > 1) {\n                                this.previousFilter = character;\n                                this.filterTimer = this._delay(function () {\n                                    delete this.previousFilter;\n                                }, 1000);\n                            } else {\n                                delete this.previousFilter;\n                            }\n                        } else {\n                            delete this.previousFilter;\n                        }\n                }\n            }\n\n            /* eslint-enable max-depth */\n            if (preventDefault) {\n                event.preventDefault();\n            }\n        },\n\n        /**\n         * @private\n         */\n        _toggleMobileMode: function () {\n            var subMenus;\n\n            $(this.element).off('mouseenter mouseleave');\n            this._on({\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                'click .ui-menu-item:has(a)': function (event) {\n                    var target;\n\n                    event.preventDefault();\n                    target = $(event.target).closest('.ui-menu-item');\n                    target.get(0).scrollIntoView();\n\n                    // Open submenu on click\n                    if (target.has('.ui-menu').length) {\n                        this.expand(event);\n                    } else if (!this.element.is(':focus') &&\n                        $(this.document[0].activeElement).closest('.ui-menu').length\n                    ) {\n                        // Redirect focus to the menu\n                        this.element.trigger('focus', [true]);\n\n                        // If the active item is on the top level, let it stay active.\n                        // Otherwise, blur the active item since it is no longer visible.\n                        if (this.active && this.active.parents('.ui-menu').length === 1) { //eslint-disable-line\n                            clearTimeout(this.timer);\n                        }\n                    }\n\n                    if (!target.hasClass('level-top') || !target.has('.ui-menu').length) {\n                        window.location.href = target.find('> a').attr('href');\n                    }\n                },\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                'click .ui-menu-item:has(.ui-state-active)': function (event) {\n                    this.collapseAll(event, true);\n                }\n            });\n\n            subMenus = this.element.find('.level-top');\n            $.each(subMenus, $.proxy(function (index, item) {\n                var category = $(item).find('> a span').not('.ui-menu-icon').text(),\n                    categoryUrl = $(item).find('> a').attr('href'),\n                    menu = $(item).find('> .ui-menu');\n\n                this.categoryLink = $('<a>')\n                    .attr('href', categoryUrl)\n                    .text($.mage.__('All %1').replace('%1', category));\n\n                this.categoryParent = $('<li>')\n                    .addClass('ui-menu-item all-category')\n                    .html(this.categoryLink);\n\n                if (menu.find('.all-category').length === 0) {\n                    menu.prepend(this.categoryParent);\n                }\n\n            }, this));\n        },\n\n        /**\n         * @private\n         */\n        _toggleDesktopMode: function () {\n            var categoryParent, html;\n\n            $(this.element).off('click mousedown mouseenter mouseleave');\n            this._on({\n\n                /**\n                 * Prevent focus from sticking to links inside menu after clicking\n                 * them (focus should always stay on UL during navigation).\n                 */\n                'mousedown .ui-menu-item > a': function (event) {\n                    event.preventDefault();\n                },\n\n                /**\n                 * Prevent focus from sticking to links inside menu after clicking\n                 * them (focus should always stay on UL during navigation).\n                 */\n                'click .ui-state-disabled > a': function (event) {\n                    event.preventDefault();\n                },\n\n                /**\n                 * @param {jQuer.Event} event\n                 */\n                'click .ui-menu-item:has(a)': function (event) {\n                    var target = $(event.target).closest('.ui-menu-item');\n\n                    if (!this.mouseHandled && target.not('.ui-state-disabled').length) {\n                        this.select(event);\n\n                        // Only set the mouseHandled flag if the event will bubble, see #9469.\n                        if (!event.isPropagationStopped()) {\n                            this.mouseHandled = true;\n                        }\n\n                        // Open submenu on click\n                        if (target.has('.ui-menu').length) {\n                            this.expand(event);\n                        } else if (!this.element.is(':focus') &&\n                            $(this.document[0].activeElement).closest('.ui-menu').length\n                        ) {\n                            // Redirect focus to the menu\n                            this.element.trigger('focus', [true]);\n\n                            // If the active item is on the top level, let it stay active.\n                            // Otherwise, blur the active item since it is no longer visible.\n                            if (this.active && this.active.parents('.ui-menu').length === 1) { //eslint-disable-line\n                                clearTimeout(this.timer);\n                            }\n                        }\n                    }\n                },\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                'mouseenter .ui-menu-item': function (event) {\n                    var target = $(event.currentTarget),\n                        submenu = this.options.menus,\n                        ulElement,\n                        ulElementWidth,\n                        width,\n                        targetPageX,\n                        rightBound;\n\n                    if (target.has(submenu)) {\n                        ulElement = target.find(submenu);\n                        ulElementWidth = ulElement.outerWidth(true);\n                        width = target.outerWidth() * 2;\n                        targetPageX = target.offset().left;\n                        rightBound = $(window).width();\n\n                        if (ulElementWidth + width + targetPageX > rightBound) {\n                            ulElement.addClass('submenu-reverse');\n                        }\n\n                        if (targetPageX - ulElementWidth < 0) {\n                            ulElement.removeClass('submenu-reverse');\n                        }\n                    }\n\n                    // Remove ui-state-active class from siblings of the newly focused menu item\n                    // to avoid a jump caused by adjacent elements both having a class with a border\n                    target.siblings().children('.ui-state-active').removeClass('ui-state-active');\n                    this.focus(event, target);\n                },\n\n                /**\n                 * @param {jQuery.Event} event\n                 */\n                'mouseleave': function (event) {\n                    this.collapseAll(event, true);\n                },\n\n                /**\n                 * Mouse leave.\n                 */\n                'mouseleave .ui-menu': 'collapseAll'\n            });\n\n            categoryParent = this.element.find('.all-category');\n            html = $('html');\n\n            categoryParent.remove();\n\n            if (html.hasClass('nav-open')) {\n                html.removeClass('nav-open');\n                setTimeout(function () {\n                    html.removeClass('nav-before-open');\n                }, this.options.hideDelay);\n            }\n        },\n\n        /**\n         * @param {*} handler\n         * @param {Number} delay\n         * @return {Number}\n         * @private\n         */\n        _delay: function (handler, delay) {\n            var instance = this,\n\n                /**\n                 * @return {*}\n                 */\n                handlerProxy = function () {\n                    return (typeof handler === 'string' ? instance[handler] : handler).apply(instance, arguments);\n                };\n\n            return setTimeout(handlerProxy, delay || 0);\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        expand: function (event) {\n            var newItem = this.active &&\n                this.active\n                    .children('.ui-menu')\n                    .children('.ui-menu-item')\n                    .first();\n\n            if (newItem && newItem.length) {\n                if (newItem.closest('.ui-menu').is(':visible') &&\n                    newItem.closest('.ui-menu').has('.all-categories')\n                ) {\n                    return;\n                }\n\n                // remove the active state class from the siblings\n                this.active.siblings().children('.ui-state-active').removeClass('ui-state-active');\n\n                this._open(newItem.parent());\n\n                // Delay so Firefox will not hide activedescendant change in expanding submenu from AT\n                this._delay(function () {\n                    this.focus(event, newItem);\n                });\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         */\n        select: function (event) {\n            var ui;\n\n            this.active = this.active || $(event.target).closest('.ui-menu-item');\n\n            if (this.active.is('.all-category')) {\n                this.active = $(event.target).closest('.ui-menu-item');\n            }\n            ui = {\n                item: this.active\n            };\n\n            if (!this.active.has('.ui-menu').length) {\n                this.collapseAll(event, true);\n            }\n            this._trigger('select', event, ui);\n        }\n    });\n\n    $.widget('mage.navigation', $.mage.menu, {\n        options: {\n            responsiveAction: 'wrap', //option for responsive handling\n            maxItems: null, //option to set max number of menu items\n            container: '#menu', //container to check against navigation length\n            moreText: $.mage.__('more'),\n            breakpoint: 768\n        },\n\n        /**\n         * @private\n         */\n        _init: function () {\n            var that, responsive;\n\n            this._super();\n\n            that = this;\n            responsive = this.options.responsiveAction;\n\n            this.element\n                .addClass('ui-menu-responsive')\n                .attr('responsive', 'main');\n\n            this.setupMoreMenu();\n            this.setMaxItems();\n\n            //check responsive option\n            if (responsive == 'onResize') { //eslint-disable-line eqeqeq\n                $(window).on('resize', function () {\n                    if ($(window).width() > that.options.breakpoint) {\n                        that._responsive();\n                        $('[responsive=more]').show();\n                    } else {\n                        that.element.children().show();\n                        $('[responsive=more]').hide();\n                    }\n                });\n            } else if (responsive == 'onReload') { //eslint-disable-line eqeqeq\n                this._responsive();\n            }\n        },\n\n        /**\n         * Setup more menu.\n         */\n        setupMoreMenu: function () {\n            var moreListItems = this.element.children().clone(),\n                moreLink = $('<a>' + this.options.moreText + '</a>');\n\n            moreListItems.hide();\n\n            moreLink.attr('href', '#');\n\n            this.moreItemsList = $('<ul>')\n                .append(moreListItems);\n\n            this.moreListContainer = $('<li>')\n                .append(moreLink)\n                .append(this.moreItemsList);\n\n            this.responsiveMenu = $('<ul>')\n                .addClass('ui-menu-more')\n                .attr('responsive', 'more')\n                .append(this.moreListContainer)\n                .menu({\n                    position: {\n                        my: 'right top',\n                        at: 'right bottom'\n                    }\n                })\n                .insertAfter(this.element);\n        },\n\n        /**\n         * @private\n         */\n        _responsive: function () {\n            var container = $(this.options.container),\n                containerSize = container.width(),\n                width = 0,\n                items = this.element.children('li'),\n                more = $('.ui-menu-more > li > ul > li a');\n\n            items = items.map(function () {\n                var item = {};\n\n                item.item = $(this);\n                item.itemSize = $(this).outerWidth();\n\n                return item;\n            });\n\n            $.each(items, function (index) {\n                var itemText = items[index].item\n                    .find('a:first')\n                    .text();\n\n                width += parseInt(items[index].itemSize, null); //eslint-disable-line radix\n\n                if (width < containerSize) {\n                    items[index].item.show();\n\n                    more.each(function () {\n                        var text = $(this).text();\n\n                        if (text === itemText) {\n                            $(this).parent().hide();\n                        }\n                    });\n                } else if (width > containerSize) {\n                    items[index].item.hide();\n\n                    more.each(function () {\n                        var text = $(this).text();\n\n                        if (text === itemText) {\n                            $(this).parent().show();\n                        }\n                    });\n                }\n            });\n        },\n\n        /**\n         * Set max items.\n         */\n        setMaxItems: function () {\n            var items = this.element.children('li'),\n                itemsCount = items.length,\n                maxItems = this.options.maxItems,\n                overflow = itemsCount - maxItems,\n                overflowItems = items.slice(overflow);\n\n            overflowItems.hide();\n\n            overflowItems.each(function () {\n                var itemText = $(this).find('a:first').text();\n\n                $(this).hide();\n\n                $('.ui-menu-more > li > ul > li a').each(function () {\n                    var text = $(this).text();\n\n                    if (text === itemText) {\n                        $(this).parent().show();\n                    }\n                });\n            });\n        }\n    });\n\n    return {\n        menu: $.mage.menu,\n        navigation: $.mage.navigation\n    };\n});\n","mage/translate-inline.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/template',\n    'mage/utils/misc',\n    'mage/translate',\n    'jquery-ui-modules/dialog'\n], function ($, mageTemplate, miscUtils) {\n    'use strict';\n\n    $.widget('mage.translateInline', $.ui.dialog, {\n        options: {\n            translateForm: {\n                template: '#translate-form-template',\n                data: {\n                    id: 'translate-inline-form',\n                    message: 'Please refresh the page to see your changes after submitting this form. ' +\n                        'Note: browser cache refresh may be required'\n                }\n            },\n            autoOpen: false,\n            translateArea: null,\n            modal: true,\n            dialogClass: 'popup-window window-translate-inline',\n            width: '75%',\n            title: $.mage.__('Translate'),\n            height: 470,\n            position: {\n                my: 'left top',\n                at: 'center top',\n                of: 'body'\n            },\n            buttons: [{\n                text: $.mage.__('Submit'),\n                'class': 'action-primary',\n\n                /**\n                 * Click\n                 */\n                click: function () {\n                    $(this).translateInline('submit');\n                }\n            },\n            {\n                text: $.mage.__('Close'),\n                'class': 'action-close',\n\n                /**\n                 * Click.\n                 */\n                click: function () {\n                    $(this).translateInline('close');\n                }\n            }],\n\n            /**\n             * Open.\n             */\n            open: function () {\n                var $uiDialog = $(this).closest('.ui-dialog'),\n                    topMargin = $uiDialog.children('.ui-dialog-titlebar').outerHeight() + 45;\n\n                $uiDialog\n                    .addClass('ui-dialog-active')\n                    .css('margin-top', topMargin);\n            },\n\n            /**\n             * Close.\n             */\n            close: function () {\n                $(this).closest('.ui-dialog').removeClass('ui-dialog-active');\n            }\n        },\n\n        /**\n         * Translate Inline creation\n         * @protected\n         */\n        _create: function () {\n            var $translateArea = $(this.options.translateArea);\n\n            if (!$translateArea.length) {\n                $translateArea = $('body');\n            }\n            $translateArea.on('edit.editTrigger', $.proxy(this._onEdit, this));\n\n            this.tmpl = mageTemplate(this.options.translateForm.template);\n\n            this._super();\n        },\n\n        /**\n         * @param {*} templateData\n         * @return {*|jQuery|HTMLElement}\n         * @private\n         */\n        _prepareContent: function (templateData) {\n            var data = $.extend({\n                items: templateData,\n                escape: miscUtils.escape\n            }, this.options.translateForm.data);\n\n            this.data = data;\n\n            return $(this.tmpl({\n                data: data\n            }));\n        },\n\n        /**\n         * Render translation form and open dialog\n         * @param {Object} e - object\n         * @protected\n         */\n        _onEdit: function (e) {\n            this.target = e.target;\n            this.element.html(this._prepareContent($(e.target).data('translate')));\n            this.open(e);\n        },\n\n        /**\n         * Submit.\n         */\n        submit: function () {\n            if (this.formIsSubmitted) {\n                return;\n            }\n            this._formSubmit();\n        },\n\n        /**\n         * Send ajax request on form submit\n         * @protected\n         */\n        _formSubmit: function () {\n            var parameters = $.param({\n                    area: this.options.area\n                }) + '&' + $('#' + this.options.translateForm.data.id).serialize();\n\n            this.formIsSubmitted = true;\n\n            $.ajax({\n                url: this.options.ajaxUrl,\n                type: 'POST',\n                data: parameters,\n                loaderContext: this.element,\n                showLoader: true\n            }).always($.proxy(this._formSubmitComplete, this));\n        },\n\n        /**\n         * @param {Object} response\n         * @private\n         */\n        _formSubmitComplete: function (response) {\n            var responseJSON = response.responseJSON || response;\n\n            this.close();\n            this.formIsSubmitted = false;\n            $.mage.translate.add(responseJSON);\n            this._updatePlaceholder(responseJSON[this.data.items[0].original]);\n        },\n\n        /**\n         * @param {*} newValue\n         * @private\n         */\n        _updatePlaceholder: function (newValue) {\n            var $target = $(this.target),\n                translateObject = $target.data('translate')[0];\n\n            translateObject.shown = newValue;\n            translateObject.translated = newValue;\n            $.mage.translate.add(this.data.items[0].original, newValue);\n\n            $target.html(newValue);\n        },\n\n        /**\n         * Destroy translateInline\n         */\n        destroy: function () {\n            this.element.off('.editTrigger');\n            this._super();\n        }\n    });\n\n    return $.mage.translateInline;\n});\n","mage/redirect-url.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.redirectUrl', {\n        options: {\n            event: 'click',\n            url: undefined\n        },\n\n        /**\n         * This method binds elements found in this widget.\n         * @private\n         */\n        _bind: function () {\n            var handlers = {};\n\n            handlers[this.options.event] = '_onEvent';\n            this._on(handlers);\n        },\n\n        /**\n         * This method constructs a new widget.\n         * @private\n         */\n        _create: function () {\n            this._bind();\n        },\n\n        /**\n         * This method set the url for the redirect.\n         * @private\n         */\n        _onEvent: function () {\n            if (this.options.url) {\n                location.href = this.options.url;\n            } else {\n                location.href = this.element.val();\n            }\n        }\n    });\n\n    return $.mage.redirectUrl;\n});\n","mage/dataPost.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/template',\n    'Magento_Ui/js/modal/confirm',\n    'jquery-ui-modules/widget'\n], function ($, mageTemplate, uiConfirm) {\n    'use strict';\n\n    $.widget('mage.dataPost', {\n        options: {\n            formTemplate: '<form action=\"<%- data.action %>\" method=\"post\">' +\n            '<% _.each(data.data, function(value, index) { %>' +\n            '<input name=\"<%- index %>\" value=\"<%- value %>\">' +\n            '<% }) %></form>',\n            postTrigger: ['a[data-post]', 'button[data-post]', 'span[data-post]'],\n            formKeyInputSelector: 'input[name=\"form_key\"]'\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            this._bind();\n        },\n\n        /** @inheritdoc */\n        _bind: function () {\n            var events = {};\n\n            $.each(this.options.postTrigger, function (index, value) {\n                events['click ' + value] = '_postDataAction';\n            });\n\n            this._on(events);\n        },\n\n        /**\n         * Handler for click.\n         *\n         * @param {Object} e\n         * @private\n         */\n        _postDataAction: function (e) {\n            var params = $(e.currentTarget).data('post');\n\n            e.preventDefault();\n            this.postData(params);\n        },\n\n        /**\n         * Data post action.\n         *\n         * @param {Object} params\n         */\n        postData: function (params) {\n            var formKey = $(this.options.formKeyInputSelector).val(),\n                $form, input;\n\n            if (formKey) {\n                params.data['form_key'] = formKey;\n            }\n\n            $form = $(mageTemplate(this.options.formTemplate, {\n                data: params\n            }));\n\n            if (params.files) {\n                $form[0].enctype = 'multipart/form-data';\n                $.each(params.files, function (key, files) {\n                    if (files instanceof FileList) {\n                        input = document.createElement('input');\n                        input.type = 'file';\n                        input.name = key;\n                        input.files = files;\n                        $form[0].appendChild(input);\n                    }\n                });\n            }\n\n            if (params.data.confirmation) {\n                uiConfirm({\n                    content: params.data.confirmationMessage,\n                    actions: {\n                        /** @inheritdoc */\n                        confirm: function () {\n                            $form.appendTo('body').hide().trigger('submit');\n                        }\n                    }\n                });\n            } else {\n                $form.appendTo('body').hide().trigger('submit');\n            }\n        }\n    });\n\n    $(document).dataPost();\n\n    return $.mage.dataPost;\n});\n","mage/trim-input.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget'\n], function ($) {\n    'use strict';\n\n    $.widget('mage.trimInput', {\n        options: {\n            cache: {}\n        },\n\n        /**\n         * Widget initialization\n         * @private\n         */\n        _create: function () {\n            this.options.cache.input = $(this.element);\n            this._bind();\n        },\n\n        /**\n         * Event binding, will monitor change, keyup and paste events.\n         * @private\n         */\n        _bind: function () {\n            if (this.options.cache.input.length) {\n                this._on(this.options.cache.input, {\n                    'change': this._trimInput,\n                    'keyup': this._trimInput,\n                    'paste': this._trimInput\n                });\n            }\n        },\n\n        /**\n         * Trim value\n         * @private\n         */\n        _trimInput: function () {\n            // Safari caret position workaround: storing carter position\n            var caretStart, caretEnd, input;\n\n            caretStart = this.options.cache.input.get(0).selectionStart;\n            caretEnd = this.options.cache.input.get(0).selectionEnd;\n\n            input = this._getInputValue().trim();\n\n            this.options.cache.input.val(input);\n\n            // Safari caret position workaround: setting caret position to previously stored values\n            if (caretStart !== null && caretEnd !== null) {\n                this.options.cache.input.get(0).setSelectionRange(caretStart, caretEnd);\n            }\n        },\n\n        /**\n         * Get input value\n         * @returns {*}\n         * @private\n         */\n        _getInputValue: function () {\n            return this.options.cache.input.val();\n        }\n    });\n\n    return $.mage.trimInput;\n});\n","mage/collapsible.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'jquery-ui-modules/widget',\n    'jquery-ui-modules/core',\n    'jquery/jquery-storageapi',\n    'mage/mage'\n], function ($) {\n    'use strict';\n\n    var hideProps = {},\n        showProps = {};\n\n    hideProps.height = 'hide';\n    showProps.height = 'show';\n\n    $.widget('mage.collapsible', {\n        options: {\n            active: false,\n            disabled: false,\n            collapsible: true,\n            header: '[data-role=title]',\n            content: '[data-role=content]',\n            trigger: '[data-role=trigger]',\n            closedState: null,\n            openedState: null,\n            disabledState: null,\n            ajaxUrlElement: '[data-ajax=true]',\n            ajaxContent: false,\n            loadingClass: null,\n            saveState: false,\n            animate: false,\n            icons: {\n                activeHeader: null,\n                header: null\n            },\n            collateral: {\n                element: null,\n                openedState: null\n            }\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            this.storage = $.localStorage;\n            this.icons = false;\n\n            if (typeof this.options.icons === 'string') {\n                this.options.icons = JSON.parse(this.options.icons);\n            }\n\n            this._processPanels();\n            this._processState();\n            this._refresh();\n\n            if (this.options.icons.header && this.options.icons.activeHeader) {\n                this._createIcons();\n                this.icons = true;\n            }\n\n            this.element.on('dimensionsChanged', function (e) {\n                if (e.target && e.target.classList.contains('active')) {\n                    this._scrollToTopIfNotVisible();\n                }\n            }.bind(this));\n\n            this._bind('click');\n            this._trigger('created');\n        },\n\n        /**\n         * @private\n         */\n        _refresh: function () {\n            this.trigger.attr('tabIndex', 0);\n\n            if (this.options.active && !this.options.disabled) {\n                if (this.options.openedState) {\n                    this.element.addClass(this.options.openedState);\n                }\n\n                if (this.options.collateral.element && this.options.collateral.openedState) {\n                    $(this.options.collateral.element).addClass(this.options.collateral.openedState);\n                }\n\n                if (this.options.ajaxContent) {\n                    this._loadContent();\n                }\n                // ARIA (updates aria attributes)\n                this.header.attr({\n                    'aria-selected': false\n                });\n            } else if (this.options.disabled) {\n                this.disable();\n            } else {\n                this.content.hide();\n\n                if (this.options.closedState) {\n                    this.element.addClass(this.options.closedState);\n                }\n            }\n        },\n\n        /**\n         * Processing the state:\n         *     If deep linking is used and the anchor is the id of the content or the content contains this id,\n         *     and the collapsible element is a nested one having collapsible parents, in order to see the content,\n         *     all the parents must be expanded.\n         * @private\n         */\n        _processState: function () {\n            var anchor = window.location.hash,\n                isValid = $.mage.isValidSelector(anchor),\n                urlPath = window.location.pathname.replace(/\\./g, ''),\n                state;\n\n            this.stateKey = encodeURIComponent(urlPath + this.element.attr('id'));\n\n            if (isValid &&\n                ($(this.content.find(anchor)).length > 0 || this.content.attr('id') === anchor.replace('#', ''))\n            ) {\n                this.element.parents('[data-collapsible=true]').collapsible('forceActivate');\n\n                if (!this.options.disabled) {\n                    this.options.active = true;\n\n                    if (this.options.saveState) { //eslint-disable-line max-depth\n                        this.storage.set(this.stateKey, true);\n                    }\n                }\n            } else if (this.options.saveState && !this.options.disabled) {\n                state = this.storage.get(this.stateKey);\n\n                if (typeof state === 'undefined' || state === null) {\n                    this.storage.set(this.stateKey, this.options.active);\n                } else if (state === true) {\n                    this.options.active = true;\n                } else if (state === false) {\n                    this.options.active = false;\n                }\n            }\n        },\n\n        /**\n         * @private\n         */\n        _createIcons: function () {\n            var icons = this.options.icons;\n\n            if (icons) {\n                $('<span>')\n                    .addClass(icons.header)\n                    .attr('data-role', 'icons')\n                    .prependTo(this.header);\n\n                if (this.options.active && !this.options.disabled) {\n                    this.header.children('[data-role=icons]')\n                        .removeClass(icons.header)\n                        .addClass(icons.activeHeader);\n                }\n            }\n        },\n\n        /**\n         * @private\n         */\n        _destroyIcons: function () {\n            this.header\n                .children('[data-role=icons]')\n                .remove();\n        },\n\n        /**\n         * @private\n         */\n        _destroy: function () {\n            var options = this.options;\n\n            this.element.removeAttr('data-collapsible');\n\n            this.trigger.removeAttr('tabIndex');\n\n            if (options.openedState) {\n                this.element.removeClass(options.openedState);\n            }\n\n            if (this.options.collateral.element && this.options.collateral.openedState) {\n                $(this.options.collateral.element).removeClass(this.options.collateral.openedState);\n            }\n\n            if (options.closedState) {\n                this.element.removeClass(options.closedState);\n            }\n\n            if (options.disabledState) {\n                this.element.removeClass(options.disabledState);\n            }\n\n            if (this.icons) {\n                this._destroyIcons();\n            }\n        },\n\n        /**\n         * @private\n         */\n        _processPanels: function () {\n            var headers, triggers;\n\n            this.element.attr('data-collapsible', 'true');\n\n            if (typeof this.options.header === 'object') {\n                this.header = this.options.header;\n            } else {\n                headers = this.element.find(this.options.header);\n\n                if (headers.length > 0) {\n                    this.header = headers.eq(0);\n                } else {\n                    this.header = this.element;\n                }\n            }\n\n            if (typeof this.options.content === 'object') {\n                this.content = this.options.content;\n            } else {\n                this.content = this.header.next(this.options.content).eq(0);\n            }\n\n            // ARIA (init aria attributes)\n            if (this.header.attr('id')) {\n                this.content.attr('aria-labelledby', this.header.attr('id'));\n            }\n\n            if (this.content.attr('id')) {\n                this.header.attr('aria-controls', this.content.attr('id'));\n            }\n\n            this.header\n                .attr({\n                    'role': 'tab',\n                    'aria-selected': this.options.active,\n                    'aria-expanded': this.options.active\n                });\n\n            // For collapsible widget only (not tabs or accordion)\n            if (this.header.parent().attr('role') !== 'presentation') {\n                this.header\n                    .parent()\n                    .attr('role', 'tablist');\n            }\n\n            this.content.attr({\n                'role': 'tabpanel',\n                'aria-hidden': !this.options.active\n            });\n\n            if (typeof this.options.trigger === 'object') {\n                this.trigger = this.options.trigger;\n            } else {\n                triggers = this.header.find(this.options.trigger);\n\n                if (triggers.length > 0) {\n                    this.trigger = triggers.eq(0);\n                } else {\n                    this.trigger = this.header;\n                }\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _keydown: function (event) {\n            var keyCode;\n\n            if (event.altKey || event.ctrlKey) {\n                return;\n            }\n\n            keyCode = $.ui.keyCode;\n\n            switch (event.keyCode) {\n                case keyCode.SPACE:\n                case keyCode.ENTER:\n                    this._eventHandler(event);\n                    break;\n            }\n\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _bind: function (event) {\n            var self = this;\n\n            this.events = {\n                keydown: '_keydown'\n            };\n\n            if (event) {\n                $.each(event.split(' '), function (index, eventName) {\n                    self.events[eventName] = '_eventHandler';\n                });\n            }\n            this._off(this.trigger);\n\n            if (!this.options.disabled) {\n                this._on(this.trigger, this.events);\n            }\n        },\n\n        /**\n         * Disable.\n         */\n        disable: function () {\n            this.options.disabled = true;\n            this._off(this.trigger);\n            this.forceDeactivate();\n\n            if (this.options.disabledState) {\n                this.element.addClass(this.options.disabledState);\n            }\n            this.trigger.attr('tabIndex', -1);\n        },\n\n        /**\n         * Enable.\n         */\n        enable: function () {\n            this.options.disabled = false;\n            this._on(this.trigger, this.events);\n            this.forceActivate();\n\n            if (this.options.disabledState) {\n                this.element.removeClass(this.options.disabledState);\n            }\n            this.trigger.attr('tabIndex', 0);\n        },\n\n        /**\n         * @param {jQuery.Event} event\n         * @private\n         */\n        _eventHandler: function (event) {\n\n            if (this.options.active && this.options.collapsible) {\n                this.deactivate();\n            } else {\n                this.activate();\n\n            }\n            event.preventDefault();\n\n        },\n\n        /**\n         * @param {*} prop\n         * @private\n         */\n        _animate: function (prop) {\n            var duration,\n                easing,\n                animate = this.options.animate;\n\n            if (typeof animate === 'number') {\n                duration = animate;\n            }\n\n            if (typeof animate === 'string') {\n                animate = JSON.parse(animate);\n            }\n            duration = duration || animate.duration;\n            easing = animate.easing;\n            this.content.animate(prop, duration, easing);\n        },\n\n        /**\n         * Deactivate.\n         */\n        deactivate: function () {\n            if (this.options.animate) {\n                this._animate(hideProps);\n            } else {\n                this.content.hide();\n            }\n            this._close();\n        },\n\n        /**\n         * Force deactivate.\n         */\n        forceDeactivate: function () {\n            this.content.hide();\n            this._close();\n\n        },\n\n        /**\n         * @private\n         */\n        _close: function () {\n            this.options.active = false;\n\n            if (this.options.saveState) {\n                this.storage.set(this.stateKey, false);\n            }\n\n            if (this.options.openedState) {\n                this.element.removeClass(this.options.openedState);\n            }\n\n            if (this.options.collateral.element && this.options.collateral.openedState) {\n                $(this.options.collateral.element).removeClass(this.options.collateral.openedState);\n            }\n\n            if (this.options.closedState) {\n                this.element.addClass(this.options.closedState);\n            }\n\n            if (this.icons) {\n                this.header.children('[data-role=icons]')\n                    .removeClass(this.options.icons.activeHeader)\n                    .addClass(this.options.icons.header);\n            }\n\n            // ARIA (updates aria attributes)\n            this.header.attr({\n                'aria-selected': 'false',\n                'aria-expanded': 'false'\n            });\n            this.content.attr({\n                'aria-hidden': 'true'\n            });\n\n            this.element.trigger('dimensionsChanged', {\n                opened: false\n            });\n        },\n\n        /**\n         * Activate.\n         *\n         * @return void;\n         */\n        activate: function () {\n            if (this.options.disabled) {\n                return;\n            }\n\n            if (this.options.animate) {\n                this._animate(showProps);\n            } else {\n                this.content.show();\n            }\n            this._open();\n        },\n\n        /**\n         * Force activate.\n         */\n        forceActivate: function () {\n            if (!this.options.disabled) {\n                this.content.show();\n                this._open();\n            }\n        },\n\n        /**\n         * @private\n         */\n        _open: function () {\n            this.element.trigger('beforeOpen');\n            this.options.active = true;\n\n            if (this.options.ajaxContent) {\n                this._loadContent();\n            }\n\n            if (this.options.saveState) {\n                this.storage.set(this.stateKey, true);\n            }\n\n            if (this.options.openedState) {\n                this.element.addClass(this.options.openedState);\n            }\n\n            if (this.options.collateral.element && this.options.collateral.openedState) {\n                $(this.options.collateral.element).addClass(this.options.collateral.openedState);\n            }\n\n            if (this.options.closedState) {\n                this.element.removeClass(this.options.closedState);\n            }\n\n            if (this.icons) {\n                this.header.children('[data-role=icons]')\n                    .removeClass(this.options.icons.header)\n                    .addClass(this.options.icons.activeHeader);\n            }\n\n            // ARIA (updates aria attributes)\n            this.header.attr({\n                'aria-selected': 'true',\n                'aria-expanded': 'true'\n            });\n            this.content.attr({\n                'aria-hidden': 'false'\n            });\n\n            this.element.trigger('dimensionsChanged', {\n                opened: true\n            });\n        },\n\n        /**\n         * @private\n         */\n        _loadContent: function () {\n            var url = this.element.find(this.options.ajaxUrlElement).attr('href'),\n                that = this;\n\n            if (url) {\n                that.xhr = $.get({\n                    url: url,\n                    dataType: 'html'\n                }, function () {\n                });\n            }\n\n            if (that.xhr && that.xhr.statusText !== 'canceled') {\n                if (that.options.loadingClass) {\n                    that.element.addClass(that.options.loadingClass);\n                }\n                that.content.attr('aria-busy', 'true');\n                that.xhr.done(function (response) {\n                    setTimeout(function () {\n                        that.content.html(response);\n                    }, 1);\n                });\n                that.xhr.always(function (jqXHR, status) {\n                    setTimeout(function () {\n                        if (status === 'abort') {\n                            that.content.stop(false, true);\n                        }\n\n                        if (that.options.loadingClass) {\n                            that.element.removeClass(that.options.loadingClass);\n                        }\n                        that.content.removeAttr('aria-busy');\n\n                        if (jqXHR === that.xhr) {\n                            delete that.xhr;\n                        }\n                    }, 1);\n                });\n            }\n        },\n\n        /**\n         * @private\n         */\n        _scrollToTopIfNotVisible: function () {\n            if (this._isElementOutOfViewport()) {\n                this.header[0].scrollIntoView();\n            }\n        },\n\n        /**\n         * @private\n         * @return {Boolean}\n         */\n        _isElementOutOfViewport: function () {\n            var headerRect = this.header[0].getBoundingClientRect(),\n                contentRect = this.content.get().length ? this.content[0].getBoundingClientRect() : false,\n                headerOut,\n                contentOut;\n\n            headerOut = headerRect.bottom - headerRect.height < 0 ||\n                headerRect.right - headerRect.width < 0 ||\n                headerRect.left + headerRect.width > window.innerWidth ||\n                headerRect.top + headerRect.height > window.innerHeight;\n\n            contentOut = contentRect ? contentRect.bottom - contentRect.height < 0 ||\n                contentRect.right - contentRect.width < 0 ||\n                contentRect.left + contentRect.width > window.innerWidth ||\n                contentRect.top + contentRect.height > window.innerHeight : false;\n\n            return headerOut ? headerOut : contentOut;\n        }\n    });\n\n    return $.mage.collapsible;\n});\n","mage/terms.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @deprecated since version 2.2.0\n */\ndefine([\n    'jquery'\n], function ($) {\n    'use strict';\n\n    /**\n     * @param {*} args\n     */\n    $.fn.terms = function (args) {\n\n        // default\n        var defaults = {\n                start: 0,\n                wrapper: '',\n                showAnchor: '',\n                effects: 'slide'\n            },\n            options = $.extend(defaults, args);\n\n        this.each(function () {\n            var obj = $(this),\n                wrapper = options.wrapper !== '' ? '> ' + options.wrapper : '',\n                switches = $(wrapper + '> [data-section=\"title\"] > [data-toggle=\"switch\"]', obj),\n                terms = $(wrapper + '> [data-section=\"content\"]', obj),\n                t = switches.length,\n                marginTop = $(switches[0]).closest('[data-section=\"title\"]').css('position') == 'absolute' ? 0 : null, //eslint-disable-line\n                title,\n                current,\n\n                /**\n                 * @param {*} item\n                 */\n                showItem = function (item) {\n                    if (item != current && !$(switches[item]).closest('[data-section=\"title\"]').hasClass('disabled')) { //eslint-disable-line\n                        $(switches).closest('[data-section=\"title\"]').removeClass('active');\n\n                        if (options.wrapper !== '') {\n                            $(switches).parent().parent().removeClass('active');\n                        }\n                        $(terms).removeClass('active');\n                        $(switches[item]).closest('[data-section=\"title\"]').addClass('active');\n\n                        if (options.wrapper !== '') {\n                            $(switches[current]).parent().parent().addClass('active');\n                        }\n                        $(terms[item]).addClass('active');\n                        current = item;\n                    } else if (\n                        // Check if this is accordion width as criteria for now\n                        (obj.attr('data-sections') == 'accordion' || $(switches[item]).closest('[data-section=\"title\"]').css('width') == obj.css('width')) && //eslint-disable-line\n                        item == current && !$(switches[item]).closest('[data-section=\"title\"]').hasClass('disabled') //eslint-disable-line\n                    ) {\n                        $(switches).closest('[data-section=\"title\"]').removeClass('active');\n\n                        if (options.wrapper !== '') {\n                            $(switches).parent().parent().removeClass('active');\n                        }\n                        $(terms).removeClass('active');\n                        current = -1;\n                    }\n                },\n\n                /**\n                 * Init.\n                 */\n                init = function () {\n                    var linksList, i, classes, dataSection, itemHref, itemClass, fromUrl;\n\n                    if (t > 0) {\n                        if ($(switches[0]).closest('[data-section=\"title\"]').css('display') == 'table-cell') { //eslint-disable-line\n                            obj.addClass('adjusted');\n\n                            if (obj[0].tagName == 'DL') { //eslint-disable-line eqeqeq, max-depth\n                                linksList = $('<dd>');\n                            } else {\n                                linksList = $('<div>');\n                            }\n                            linksList.addClass('sections-nav');\n                            obj.prepend(linksList);\n\n                            for (i = 0; i < t; i++) { //eslint-disable-line max-depth\n                                title = $(switches[i]).html();\n                                classes = $(switches[i]).closest('[data-section=\"title\"]').attr('class');\n                                dataSection = $(switches[i]).closest('[data-section=\"title\"]').attr('data-section');\n                                itemHref = $(switches[i]).attr('href');\n                                itemClass = $(switches[i]).attr('class');\n                                $(switches[i]).parent('[data-section=\"title\"]').hide();\n                                switches[i] = $('<a/>', {\n                                    href: itemHref,\n                                    'class': itemClass,\n                                    html: title\n                                }).appendTo(linksList);\n                                $(switches[i]).wrap(\n                                    '<strong class=\"' + classes + '\" data-section=\"' + dataSection + '\" />'\n                                );\n                            }\n                        }\n                        $(switches).each(function (ind, el) {\n                            $(el).on('click', function (event) {\n                                event.preventDefault();\n                                showItem(ind);\n                            });\n\n                            if (marginTop !== null) {\n                                $(el).closest('[data-section=\"title\"]').css({\n                                    'top': marginTop + 'px'\n                                });\n                                marginTop += $(el).closest('[data-section=\"title\"]').outerHeight(true);\n                                obj.css({\n                                    'min-height': marginTop + 'px'\n                                });\n                            }\n                        });\n\n                        fromUrl = false;\n\n                        if (window.location.hash.length > 0) {\n                            $(terms).each(function (ind, el) {\n                                if ('#info-' + $(el).attr('id') == window.location.hash) { //eslint-disable-line eqeqeq\n                                    showItem(ind);\n                                    $('html, body').animate({\n                                        scrollTop: $(switches[ind]).offset().top\n                                    }, 700);\n                                    fromUrl = true;\n                                }\n                            });\n                        }\n\n                        if (fromUrl === false) {\n                            if (options.start % 1 === 0) { //eslint-disable-line max-depth\n                                current = options.start + 1;\n                                showItem(options.start);\n                            } else {\n                                $(terms).each(function (ind, el) {\n                                    if ($(el).attr('id') == options.start) { //eslint-disable-line eqeqeq\n                                        current = ind + 1;\n                                        showItem(ind);\n                                        $('html, body').animate({\n                                            scrollTop: $(switches[ind]).offset().top\n                                        }, 700);\n                                    }\n                                });\n                            }\n                        }\n                    }\n                };\n\n            init();\n        });\n    };\n\n    return function (data, el) {\n        $(el).terms(data);\n    };\n});\n","mage/loader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/template',\n    'jquery-ui-modules/widget',\n    'mage/translate'\n], function ($, mageTemplate) {\n    'use strict';\n\n    $.widget('mage.loader', {\n        loaderStarted: 0,\n        options: {\n            icon: '',\n            texts: {\n                loaderText: $.mage.__('Please wait...'),\n                imgAlt: $.mage.__('Loading...')\n            },\n            template:\n                '<div class=\"loading-mask\" data-role=\"loader\">' +\n                    '<div class=\"loader\">' +\n                        '<img alt=\"<%- data.texts.imgAlt %>\" src=\"<%- data.icon %>\">' +\n                        '<p><%- data.texts.loaderText %></p>' +\n                    '</div>' +\n                '</div>'\n\n        },\n\n        /**\n         * Loader creation\n         * @protected\n         */\n        _create: function () {\n            this._bind();\n        },\n\n        /**\n         * Bind on ajax events\n         * @protected\n         */\n        _bind: function () {\n            this._on({\n                'processStop': 'hide',\n                'processStart': 'show',\n                'show.loader': 'show',\n                'hide.loader': 'hide',\n                'contentUpdated.loader': '_contentUpdated'\n            });\n        },\n\n        /**\n         * Verify loader present after content updated\n         *\n         * This will be cleaned up by the task MAGETWO-11070\n         *\n         * @param {EventObject} e\n         * @private\n         */\n        _contentUpdated: function (e) {\n            this.show(e);\n        },\n\n        /**\n         * Show loader\n         */\n        show: function (e, ctx) {\n            this._render();\n            this.loaderStarted++;\n            this.spinner.show();\n\n            if (ctx) {\n                this.spinner\n                    .css({\n                        width: ctx.outerWidth(),\n                        height: ctx.outerHeight(),\n                        position: 'absolute'\n                    })\n                    .position({\n                        my: 'top left',\n                        at: 'top left',\n                        of: ctx\n                    });\n            }\n\n            return false;\n        },\n\n        /**\n         * Hide loader\n         */\n        hide: function () {\n            if (this.loaderStarted > 0) {\n                this.loaderStarted--;\n\n                if (this.loaderStarted === 0) {\n                    this.spinner.hide();\n                }\n            }\n\n            return false;\n        },\n\n        /**\n         * Render loader\n         * @protected\n         */\n        _render: function () {\n            var html;\n\n            if (!this.spinnerTemplate) {\n                this.spinnerTemplate = mageTemplate(this.options.template);\n\n                html = $(this.spinnerTemplate({\n                    data: this.options\n                }));\n\n                html.prependTo(this.element);\n\n                this.spinner = html;\n            }\n        },\n\n        /**\n         * Destroy loader\n         */\n        _destroy: function () {\n            this.spinner.remove();\n        }\n    });\n\n    /**\n     * This widget takes care of registering the needed loader listeners on the body\n     */\n    $.widget('mage.loaderAjax', {\n        options: {\n            defaultContainer: '[data-container=body]',\n            loadingClass: 'ajax-loading'\n        },\n\n        /**\n         * @private\n         */\n        _create: function () {\n            this._bind();\n            // There should only be one instance of this widget, and it should be attached\n            // to the body only. Having it on the page twice will trigger multiple processStarts.\n            if (window.console && !this.element.is(this.options.defaultContainer) && $.mage.isDevMode(undefined)) {\n                console.warn('This widget is intended to be attached to the body, not below.');\n            }\n        },\n\n        /**\n         * @private\n         */\n        _bind: function () {\n            $(document).on({\n                'ajaxSend': this._onAjaxSend.bind(this),\n                'ajaxComplete': this._onAjaxComplete.bind(this)\n            });\n        },\n\n        /**\n         * @param {Object} loaderContext\n         * @return {*}\n         * @private\n         */\n        _getJqueryObj: function (loaderContext) {\n            var ctx;\n\n            // Check to see if context is jQuery object or not.\n            if (loaderContext) {\n                if (loaderContext.jquery) {\n                    ctx = loaderContext;\n                } else {\n                    ctx = $(loaderContext);\n                }\n            } else {\n                ctx = $('[data-container=\"body\"]');\n            }\n\n            return ctx;\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @param {Object} jqxhr\n         * @param {Object} settings\n         * @private\n         */\n        _onAjaxSend: function (e, jqxhr, settings) {\n            var ctx;\n\n            $(this.options.defaultContainer)\n                .addClass(this.options.loadingClass)\n                .attr({\n                    'aria-busy': true\n                });\n\n            if (settings && settings.showLoader) {\n                ctx = this._getJqueryObj(settings.loaderContext);\n                ctx.trigger('processStart');\n\n                // Check to make sure the loader is there on the page if not report it on the console.\n                // NOTE that this check should be removed before going live. It is just an aid to help\n                // in finding the uses of the loader that maybe broken.\n                if (window.console && !ctx.parents('[data-role=\"loader\"]').length) {\n                    console.warn('Expected to start loader but did not find one in the dom');\n                }\n            }\n        },\n\n        /**\n         * @param {jQuery.Event} e\n         * @param {Object} jqxhr\n         * @param {Object} settings\n         * @private\n         */\n        _onAjaxComplete: function (e, jqxhr, settings) {\n            $(this.options.defaultContainer)\n                .removeClass(this.options.loadingClass)\n                .attr('aria-busy', false);\n\n            if (settings && settings.showLoader) {\n                this._getJqueryObj(settings.loaderContext).trigger('processStop');\n            }\n        }\n\n    });\n\n    return {\n        loader: $.mage.loader,\n        loaderAjax: $.mage.loaderAjax\n    };\n});\n","mage/requirejs/resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore',\n    'domReady!'\n], function (_) {\n    'use strict';\n\n    var context = require.s.contexts._,\n        execCb = context.execCb,\n        registry = context.registry,\n        callbacks = [],\n        retries = 10,\n        updateDelay = 1,\n        ready,\n        update;\n\n    /**\n     * Checks if provided callback already exists in the callbacks list.\n     *\n     * @param {Object} callback - Callback object to be checked.\n     * @returns {Boolean}\n     */\n    function isSubscribed(callback) {\n        return !!_.findWhere(callbacks, callback);\n    }\n\n    /**\n     * Checks if provided module is rejected during load.\n     *\n     * @param {Object} module - Module to be checked.\n     * @return {Boolean}\n     */\n    function isRejected(module) {\n        return registry[module.id] && (registry[module.id].inited || registry[module.id].error);\n    }\n\n    /**\n     * Checks if provided module had path fallback triggered.\n     *\n     * @param {Object} module - Module to be checked.\n     * @return {Boolean}\n     */\n    function isPathFallback(module) {\n        return registry[module.id] && registry[module.id].events.error;\n    }\n\n    /**\n     * Checks if provided module has unresolved dependencies.\n     *\n     * @param {Object} module - Module to be checked.\n     * @returns {Boolean}\n     */\n    function isPending(module) {\n        if (!module.depCount) {\n            return false;\n        }\n\n        return module.depCount >\n            _.filter(module.depMaps, isRejected).length + _.filter(module.depMaps, isPathFallback).length;\n    }\n\n    /**\n     * Checks if requirejs's registry object contains pending modules.\n     *\n     * @returns {Boolean}\n     */\n    function hasPending() {\n        return _.some(registry, isPending);\n    }\n\n    /**\n     * Checks if 'resolver' module is in ready\n     * state and that there are no pending modules.\n     *\n     * @returns {Boolean}\n     */\n    function isReady() {\n        return ready && !hasPending();\n    }\n\n    /**\n     * Invokes provided callback handler.\n     *\n     * @param {Object} callback\n     */\n    function invoke(callback) {\n        callback.handler.call(callback.ctx);\n    }\n\n    /**\n     * Sets 'resolver' module to a ready state\n     * and invokes pending callbacks.\n     */\n    function resolve() {\n        ready = true;\n\n        callbacks.splice(0).forEach(invoke);\n    }\n\n    /**\n     * Drops 'ready' flag and runs the update process.\n     */\n    function tick() {\n        ready = false;\n\n        update(retries);\n    }\n\n    /**\n     * Adds callback which will be invoked\n     * when all of the pending modules are initiated.\n     *\n     * @param {Function} handler - 'Ready' event handler function.\n     * @param {Object} [ctx] - Optional context with which handler\n     *      will be invoked.\n     */\n    function subscribe(handler, ctx) {\n        var callback = {\n            handler: handler,\n            ctx: ctx\n        };\n\n        if (!isSubscribed(callback)) {\n            callbacks.push(callback);\n\n            if (isReady()) {\n                _.defer(tick);\n            }\n        }\n    }\n\n    /**\n     * Checks for all modules to be initiated\n     * and invokes pending callbacks if it's so.\n     *\n     * @param {Number} [retry] - Number of retries\n     *      that will be used to repeat the 'update' function\n     *      invokation in case if there are no pending requests.\n     */\n    update = _.debounce(function (retry) {\n        if (!hasPending()) {\n            retry ? update(--retry) : resolve();\n        }\n    }, updateDelay);\n\n    /**\n     * Overrides requirejs's original 'execCb' method\n     * in order to track pending modules.\n     *\n     * @returns {*} Result of original method call.\n     */\n    context.execCb = function () {\n        var exported = execCb.apply(context, arguments);\n\n        tick();\n\n        return exported;\n    };\n\n    return subscribe;\n});\n","mage/requirejs/text.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* inspired by http://github.com/requirejs/text */\n/*global XDomainRequest */\n\ndefine(['module'], function (module) {\n    'use strict';\n\n    var xmlRegExp = /^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,\n        bodyRegExp = /<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,\n        stripReg = /!strip$/i,\n        defaultConfig = module.config && module.config() || {};\n\n    /**\n     * Strips <?xml ...?> declarations so that external SVG and XML documents can be\n     * added to a document without worry.\n     * Also, if the string is an HTML document, only the part inside the body tag is returned.\n     *\n     * @param {String} external\n     * @returns {String}\n     */\n    function stripContent(external) {\n        var matches;\n\n        if (!external) {\n            return '';\n        }\n\n        matches = external.match(bodyRegExp);\n        external = matches ?\n            matches[1] :\n            external.replace(xmlRegExp, '');\n\n        return external;\n    }\n\n    /**\n     * Checks that url match current location\n     *\n     * @param {String} url\n     * @returns {Boolean}\n     */\n    function sameDomain(url) {\n        var uProtocol, uHostName, uPort,\n            xdRegExp = /^([\\w:]+)?\\/\\/([^\\/\\\\]+)/i,\n            location = window.location,\n            match = xdRegExp.exec(url);\n\n        if (!match) {\n            return true;\n        }\n        uProtocol = match[1];\n        uHostName = match[2];\n\n        uHostName = uHostName.split(':');\n        uPort = uHostName[1] || '';\n        uHostName = uHostName[0];\n\n        return (!uProtocol || uProtocol === location.protocol) &&\n            (!uHostName || uHostName.toLowerCase() === location.hostname.toLowerCase()) &&\n            (!uPort && !uHostName || uPort === location.port);\n    }\n\n    /**\n     * @returns {XMLHttpRequest|XDomainRequest|null}\n     */\n    function createRequest(url) {\n        var xhr = new XMLHttpRequest();\n\n        if (!sameDomain(url) && typeof XDomainRequest !== 'undefined') {\n            xhr = new XDomainRequest();\n        }\n\n        return xhr;\n    }\n\n    /**\n     * XHR requester. Returns value to callback.\n     *\n     * @param {String} url\n     * @param {Function} callback\n     * @param {Function} fail\n     * @param {Object} headers\n     */\n    function getContent(url, callback, fail, headers) {\n        var xhr = createRequest(url),\n            header;\n\n        xhr.open('GET', url);\n\n        /*eslint-disable max-depth */\n        if ('setRequestHeader' in xhr && headers) {\n            for (header in headers) {\n                if (headers.hasOwnProperty(header)) {\n                    xhr.setRequestHeader(header.toLowerCase(), headers[header]);\n                }\n            }\n        }\n\n        /**\n         * @inheritdoc\n         */\n        xhr.onreadystatechange = function () {\n            var status, err;\n\n            //Do not explicitly handle errors, those should be\n            //visible via console output in the browser.\n            if (xhr.readyState === 4) {\n                status = xhr.status || 0;\n\n                if (status > 399 && status < 600) {\n                    //An http 4xx or 5xx error. Signal an error.\n                    err = new Error(url + ' HTTP status: ' + status);\n                    err.xhr = xhr;\n\n                    if (fail) {\n                        fail(err);\n                    }\n                } else {\n                    callback(xhr.responseText);\n\n                    if (defaultConfig.onXhrComplete) {\n                        defaultConfig.onXhrComplete(xhr, url);\n                    }\n                }\n            }\n        };\n\n        /*eslint-enable max-depth */\n\n        if (defaultConfig.onXhr) {\n            defaultConfig.onXhr(xhr, url);\n        }\n\n        xhr.send();\n    }\n\n    /**\n     * Main method used by RequireJs.\n     *\n     * @param {String} name - has format: some.module.filext!strip\n     * @param {Function} req\n     * @param {Function|undefined} onLoad\n     */\n    function loadContent(name, req, onLoad) {\n\n        var toStrip = stripReg.test(name),\n            url = req.toUrl(name.replace(stripReg, '')),\n            headers = defaultConfig.headers;\n\n        getContent(url, function (content) {\n                content = toStrip ? stripContent(content) : content;\n                onLoad(content);\n            }, onLoad.error, headers);\n    }\n\n    return {\n        load: loadContent,\n        get: getContent\n    };\n});\n","mage/requirejs/baseUrlResolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Sample configuration:\n *\n require.config({\n        \"config\": {\n            \"baseUrlInterceptor\": {\n                \"Magento_Ui/js/lib/knockout/bindings/collapsible.js\": \"../../../../frontend/Magento/luma/en_US/\"\n            }\n        }\n    });\n */\n\n/* global jsSuffixRegExp */\n/* eslint-disable max-depth */\ndefine('baseUrlInterceptor', [\n    'module'\n], function (module) {\n    'use strict';\n\n    /**\n     * RequireJS Context object\n     */\n    var ctx = require.s.contexts._,\n\n        /**\n         * Original function\n         *\n         * @type {Function}\n         */\n        origNameToUrl = ctx.nameToUrl,\n\n        /**\n         * Original function\n         *\n         * @type {Function}\n         */\n        newContextConstr = require.s.newContext;\n\n    /**\n     * Remove dots from URL\n     *\n     * @param {Array} ary\n     */\n    function trimDots(ary) {\n        var i, part, length = ary.length;\n\n        for (i = 0; i < length; i++) {\n            part = ary[i];\n\n            if (part === '.') {\n                ary.splice(i, 1);\n                i -= 1;\n            } else if (part === '..') {\n                if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {\n                    //End of the line. Keep at least one non-dot\n                    //path segment at the front so it can be mapped\n                    //correctly to disk. Otherwise, there is likely\n                    //no path mapping for a path starting with '..'.\n                    //This can still fail, but catches the most reasonable\n                    //uses of ..\n                    break;\n                } else if (i > 0) {\n                    ary.splice(i - 1, 2);\n                    i -= 2;\n                }\n            }\n        }\n    }\n\n    /**\n     * Normalize URL string (remove '/../')\n     *\n     * @param {String} name\n     * @param {String} baseName\n     * @param {Object} applyMap\n     * @param {Object} localContext\n     * @returns {*}\n     */\n    function normalize(name, baseName, applyMap, localContext) {\n        var lastIndex,\n            baseParts = baseName && baseName.split('/'),\n            normalizedBaseParts = baseParts;\n\n        //Adjust any relative paths.\n        if (name && name.charAt(0) === '.') {\n            //If have a base name, try to normalize against it,\n            //otherwise, assume it is a top-level require that will\n            //be relative to baseUrl in the end.\n            if (baseName) {\n                //Convert baseName to array, and lop off the last part,\n                //so that . matches that 'directory' and not name of the baseName's\n                //module. For instance, baseName of 'one/two/three', maps to\n                //'one/two/three.js', but we want the directory, 'one/two' for\n                //this normalization.\n                normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n                name = name.split('/');\n                lastIndex = name.length - 1;\n\n                // If wanting node ID compatibility, strip .js from end\n                // of IDs. Have to do this here, and not in nameToUrl\n                // because node allows either .js or non .js to map\n                // to same file.\n                if (localContext.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n                    name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n                }\n\n                name = normalizedBaseParts.concat(name);\n                trimDots(name);\n                name = name.join('/');\n            } else if (name.indexOf('./') === 0) {\n                // No baseName, so this is ID is resolved relative\n                // to baseUrl, pull off the leading dot.\n                name = name.substring(2);\n            }\n        }\n\n        return name;\n    }\n\n    /**\n     * Get full url.\n     *\n     * @param {Object} context\n     * @param {String} url\n     * @return {String}\n     */\n    function getUrl(context, url) {\n        var baseUrl = context.config.baseUrl,\n            newConfig = context.config,\n            modulePath = url.replace(baseUrl, ''),\n            newBaseUrl,\n            rewrite = module.config()[modulePath];\n\n        if (!rewrite) {\n            return url;\n        }\n\n        newBaseUrl = normalize(rewrite, baseUrl, undefined, newConfig);\n\n        return newBaseUrl + modulePath;\n    }\n\n    /**\n     * Replace original function.\n     *\n     * @returns {*}\n     */\n    ctx.nameToUrl = function () {\n        return getUrl(ctx, origNameToUrl.apply(ctx, arguments));\n    };\n\n    /**\n     * Replace original function.\n     *\n     * @return {*}\n     */\n    require.s.newContext = function () {\n        var newCtx = newContextConstr.apply(require.s, arguments),\n            newOrigNameToUrl = newCtx.nameToUrl;\n\n        /**\n         * New implementation of native function.\n         *\n         * @returns {String}\n         */\n        newCtx.nameToUrl = function () {\n            return getUrl(newCtx, newOrigNameToUrl.apply(newCtx, arguments));\n        };\n\n        return newCtx;\n    };\n});\n\nrequire(['baseUrlInterceptor'], function () {\n    'use strict';\n\n});\n","mage/gallery/gallery.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'fotorama/fotorama',\n    'underscore',\n    'matchMedia',\n    'mage/template',\n    'text!mage/gallery/gallery.html',\n    'uiClass',\n    'mage/translate'\n], function ($, fotorama, _, mediaCheck, template, galleryTpl, Class, $t) {\n    'use strict';\n\n    /**\n     * Retrieves index if the main item.\n     * @param {Array.<Object>} data - Set of gallery items.\n     */\n    var getMainImageIndex = function (data) {\n            var mainIndex;\n\n            if (_.every(data, function (item) {\n                return _.isObject(item);\n            })\n            ) {\n                mainIndex = _.findIndex(data, function (item) {\n                    return item.isMain;\n                });\n            }\n\n            return mainIndex > 0 ? mainIndex : 0;\n        },\n\n        /**\n         * Helper for parse translate property\n         *\n         * @param {Element} el - el that to parse\n         * @returns {Array} - array of properties.\n         */\n        getTranslate = function (el) {\n            var slideTransform = $(el).attr('style').split(';');\n\n            slideTransform = $.map(slideTransform, function (style) {\n                style = style.trim();\n\n                if (style.startsWith('transform: translate3d')) {\n                    return style.match(/transform: translate3d\\((.+)px,(.+)px,(.+)px\\)/);\n                }\n\n                return false;\n            });\n\n            return slideTransform.filter(Boolean);\n        },\n\n        /**\n         * @param {*} str\n         * @return {*}\n         * @private\n         */\n        _toNumber = function (str) {\n            var type = typeof str;\n\n            if (type === 'string') {\n                return parseInt(str); //eslint-disable-line radix\n            }\n\n            return str;\n        };\n\n    return Class.extend({\n\n        defaults: {\n            settings: {},\n            config: {},\n            startConfig: {}\n        },\n\n        /**\n         * Checks if device has touch interface.\n         * @return {Boolean} The result of searching touch events on device.\n         */\n        isTouchEnabled: (function () {\n            return 'ontouchstart' in document.documentElement;\n        })(),\n\n        /**\n         * Initializes gallery.\n         * @param {Object} config - Gallery configuration.\n         * @param {String} element - String selector of gallery DOM element.\n         */\n        initialize: function (config, element) {\n            var self = this;\n\n            this._super();\n\n            _.bindAll(this,\n                '_focusSwitcher'\n            );\n\n            /*turn off arrows for touch devices*/\n            if (this.isTouchEnabled) {\n                config.options.arrows = false;\n\n                if (config.fullscreen) {\n                    config.fullscreen.arrows = false;\n                }\n            }\n\n            config.options.width = _toNumber(config.options.width);\n            config.options.height = _toNumber(config.options.height);\n            config.options.thumbwidth = _toNumber(config.options.thumbwidth);\n            config.options.thumbheight = _toNumber(config.options.thumbheight);\n\n            config.options.whiteBorders = _toNumber(config.options.whiteBorders);\n\n            config.options.swipe = true;\n            this.config = config;\n\n            this.settings = {\n                $element: $(element),\n                $pageWrapper: $('.page-wrapper'),\n                currentConfig: config,\n                defaultConfig: _.clone(config),\n                fullscreenConfig: _.clone(config.fullscreen),\n                breakpoints: config.breakpoints,\n                activeBreakpoint: {},\n                fotoramaApi: null,\n                isFullscreen: false,\n                api: null,\n                data: _.clone(config.data)\n            };\n            config.options.ratio = config.options.width / config.options.height;\n            config.options.height = null;\n            if (!config.options.whiteBorders) {\n                config.options.height = $(element).height();\n            }\n\n            $.extend(true, this.startConfig, config);\n\n            this.initGallery();\n            this.initApi();\n            this.setupBreakpoints();\n            this.initFullscreenSettings();\n\n            this.settings.$element.on('click', '.fotorama__stage__frame', function () {\n                if (\n                    !$(this).parents('.fotorama__shadows--left, .fotorama__shadows--right').length &&\n                    !$(this).hasClass('fotorama-video-container')\n                ) {\n                    self.openFullScreen();\n                }\n            });\n\n            if (this.isTouchEnabled && this.settings.isFullscreen) {\n                this.settings.$element.on('tap', '.fotorama__stage__frame', function () {\n                    var translate = getTranslate($(this).parents('.fotorama__stage__shaft'));\n\n                    if (translate[1] === '0' && !$(this).hasClass('fotorama-video-container')) {\n                        self.openFullScreen();\n                        self.settings.$pageWrapper.hide();\n                    }\n                });\n            }\n        },\n\n        /**\n         * Open gallery fullscreen\n         */\n        openFullScreen: function () {\n            this.settings.api.fotorama.requestFullScreen();\n            this.settings.$fullscreenIcon.css({\n                opacity: 1,\n                visibility: 'visible',\n                display: 'block'\n            });\n        },\n\n        /**\n         * Gallery fullscreen settings.\n         */\n        initFullscreenSettings: function () {\n            var settings = this.settings,\n                self = this;\n\n            settings.$gallery = this.settings.$element.find('[data-gallery-role=\"gallery\"]');\n            settings.$fullscreenIcon = this.settings.$element.find('[data-gallery-role=\"fotorama__fullscreen-icon\"]');\n            settings.focusableStart = this.settings.$element.find('[data-gallery-role=\"fotorama__focusable-start\"]');\n            settings.focusableEnd = this.settings.$element.find('[data-gallery-role=\"fotorama__focusable-end\"]');\n            settings.closeIcon = this.settings.$element.find('[data-gallery-role=\"fotorama__fullscreen-icon\"]');\n            settings.fullscreenConfig.swipe = true;\n\n            settings.$gallery.on('fotorama:fullscreenenter', function () {\n                settings.closeIcon.show();\n                settings.focusableStart.attr('tabindex', '0');\n                settings.focusableEnd.attr('tabindex', '0');\n                settings.focusableStart.on('focusin', self._focusSwitcher);\n                settings.focusableEnd.on('focusin', self._focusSwitcher);\n                settings.api.updateOptions(settings.defaultConfig.options, true);\n                settings.api.updateOptions(settings.fullscreenConfig, true);\n\n                if (!_.isEqual(settings.activeBreakpoint, {}) && settings.breakpoints) {\n                    settings.api.updateOptions(settings.activeBreakpoint.options, true);\n                }\n                settings.isFullscreen = true;\n            });\n\n            settings.$gallery.on('fotorama:fullscreenexit', function () {\n                settings.closeIcon.hide();\n                settings.focusableStart.attr('tabindex', '-1');\n                settings.focusableEnd.attr('tabindex', '-1');\n                settings.api.updateOptions(settings.defaultConfig.options, true);\n                settings.focusableStart.off('focusin', this._focusSwitcher);\n                settings.focusableEnd.off('focusin', this._focusSwitcher);\n                settings.closeIcon.hide();\n\n                if (!_.isEqual(settings.activeBreakpoint, {}) && settings.breakpoints) {\n                    settings.api.updateOptions(settings.activeBreakpoint.options, true);\n                }\n                settings.isFullscreen = false;\n                settings.$element.data('gallery').updateOptions({\n                    swipe: true\n                });\n            });\n        },\n\n        /**\n         * Switcher focus.\n         */\n        _focusSwitcher: function (e) {\n            var target = $(e.target),\n                settings = this.settings;\n\n            if (target.is(settings.focusableStart)) {\n                this._setFocus('start');\n            } else if (target.is(settings.focusableEnd)) {\n                this._setFocus('end');\n            }\n        },\n\n        /**\n         * Set focus to element.\n         * @param {String} position - can be \"start\" and \"end\"\n         *      positions.\n         *      If position is \"end\" - sets focus to first\n         *      focusable element in modal window scope.\n         *      If position is \"start\" - sets focus to last\n         *      focusable element in modal window scope\n         */\n        _setFocus: function (position) {\n            var settings = this.settings,\n                focusableElements,\n                infelicity;\n\n            if (position === 'end') {\n                settings.$gallery.find(settings.closeIcon).trigger('focus');\n            } else if (position === 'start') {\n                infelicity = 3; //Constant for find last focusable element\n                focusableElements = settings.$gallery.find(':focusable');\n                focusableElements.eq(focusableElements.length - infelicity).trigger('focus');\n            }\n        },\n\n        /**\n         * Initializes gallery with configuration options.\n         */\n        initGallery: function () {\n            var breakpoints = {},\n                settings = this.settings,\n                config = this.config,\n                tpl = template(galleryTpl, {\n                    next: $t('Next'),\n                    previous: $t('Previous')\n                }),\n                mainImageIndex,\n                $element = settings.$element,\n                $fotoramaElement;\n\n            if (settings.breakpoints) {\n                _.each(_.values(settings.breakpoints), function (breakpoint) {\n                    var conditions;\n\n                    _.each(_.pairs(breakpoint.conditions), function (pair) {\n                        conditions = conditions ? conditions + ' and (' + pair[0] + ': ' + pair[1] + ')' :\n                            '(' + pair[0] + ': ' + pair[1] + ')';\n                    });\n                    breakpoints[conditions] = breakpoint.options;\n                });\n                settings.breakpoints = breakpoints;\n            }\n\n            _.extend(config, config.options,\n                {\n                    options: undefined,\n                    click: false,\n                    breakpoints: null\n                }\n            );\n            settings.currentConfig = config;\n\n            $element\n                .css('min-height', settings.$element.height())\n                .append(tpl);\n\n            $fotoramaElement = $element.find('[data-gallery-role=\"gallery\"]');\n\n            $fotoramaElement.fotorama(config);\n            $fotoramaElement.find('.fotorama__stage__frame.fotorama__active')\n                .one('f:load', function () {\n                    $element\n                        .removeClass('_block-content-loading')\n                        .css('min-height', '');\n                });\n            settings.$elementF = $fotoramaElement;\n            settings.fotoramaApi = $fotoramaElement.data('fotorama');\n\n            $.extend(true, config, this.startConfig);\n\n            mainImageIndex = getMainImageIndex(config.data);\n\n            if (mainImageIndex) {\n                this.settings.fotoramaApi.show({\n                    index: mainImageIndex,\n                    time: 0\n                });\n            }\n        },\n\n        /**\n         * Creates breakpoints for gallery.\n         */\n        setupBreakpoints: function () {\n            var pairs,\n                settings = this.settings,\n                config = this.config,\n                startConfig = this.startConfig,\n                isInitialized = {},\n                isTouchEnabled = this.isTouchEnabled;\n\n            if (_.isObject(settings.breakpoints)) {\n                pairs = _.pairs(settings.breakpoints);\n                _.each(pairs, function (pair) {\n                    var mediaQuery = pair[0];\n\n                    isInitialized[mediaQuery] = false;\n                    mediaCheck({\n                        media: mediaQuery,\n\n                        /**\n                         * Is triggered when breakpoint enties.\n                         */\n                        entry: function () {\n                            $.extend(true, config, _.clone(startConfig));\n\n                            settings.api.updateOptions(settings.defaultConfig.options, true);\n\n                            if (settings.isFullscreen) {\n                                settings.api.updateOptions(settings.fullscreenConfig, true);\n                            }\n\n                            if (isTouchEnabled) {\n                                settings.breakpoints[mediaQuery].options.arrows = false;\n\n                                if (settings.breakpoints[mediaQuery].options.fullscreen) {\n                                    settings.breakpoints[mediaQuery].options.fullscreen.arrows = false;\n                                }\n                            }\n\n                            settings.api.updateOptions(settings.breakpoints[mediaQuery].options, true);\n                            $.extend(true, config, settings.breakpoints[mediaQuery]);\n                            settings.activeBreakpoint = settings.breakpoints[mediaQuery];\n\n                            isInitialized[mediaQuery] = true;\n                        },\n\n                        /**\n                         * Is triggered when breakpoint exits.\n                         */\n                        exit: function () {\n                            if (isInitialized[mediaQuery]) {\n                                $.extend(true, config, _.clone(startConfig));\n                                settings.api.updateOptions(settings.defaultConfig.options, true);\n\n                                if (settings.isFullscreen) {\n                                    settings.api.updateOptions(settings.fullscreenConfig, true);\n                                }\n                                settings.activeBreakpoint = {};\n                            } else {\n                                isInitialized[mediaQuery] = true;\n                            }\n                        }\n                    });\n                });\n            }\n        },\n\n        /**\n         * Creates gallery's API.\n         */\n        initApi: function () {\n            var settings = this.settings,\n                config = this.config,\n                api = {\n\n                    /**\n                     * Contains fotorama's API methods.\n                     */\n                    fotorama: settings.fotoramaApi,\n\n                    /**\n                     * Displays the last image on preview.\n                     */\n                    last: function () {\n                        settings.fotoramaApi.show('>>');\n                    },\n\n                    /**\n                     * Displays the first image on preview.\n                     */\n                    first: function () {\n                        settings.fotoramaApi.show('<<');\n                    },\n\n                    /**\n                     * Displays previous element on preview.\n                     */\n                    prev: function () {\n                        settings.fotoramaApi.show('<');\n                    },\n\n                    /**\n                     * Displays next element on preview.\n                     */\n                    next: function () {\n                        settings.fotoramaApi.show('>');\n                    },\n\n                    /**\n                     * Displays image with appropriate count number on preview.\n                     * @param {Number} index - Number of image that should be displayed.\n                     */\n                    seek: function (index) {\n                        if (_.isNumber(index) && index !== 0) {\n\n                            if (index > 0) {\n                                index -= 1;\n                            }\n                            settings.fotoramaApi.show(index);\n                        }\n                    },\n\n                    /**\n                     * Updates gallery with new set of options.\n                     * @param {Object} configuration - Standart gallery configuration object.\n                     * @param {Boolean} isInternal - Is this function called via breakpoints.\n                     */\n                    updateOptions: function (configuration, isInternal) {\n\n                        var $selectable = $('a[href], area[href], input, select, ' +\n                                'textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]')\n                                .not('[tabindex=-1], [disabled], :hidden'),\n                            $focus = $(':focus'),\n                            index;\n\n                        if (_.isObject(configuration)) {\n\n                            //Saves index of focus\n                            $selectable.each(function (number) {\n                                if ($(this).is($focus)) {\n                                    index = number;\n                                }\n                            });\n\n                            if (this.isTouchEnabled) {\n                                configuration.arrows = false;\n                            }\n                            configuration.click = false;\n                            configuration.breakpoints = null;\n\n                            if (!isInternal) {\n                                !_.isEqual(settings.activeBreakpoint, {} && settings.breakpoints) ?\n                                    $.extend(true, settings.activeBreakpoint.options, configuration) :\n\n                                    settings.isFullscreen ?\n                                        $.extend(true, settings.fullscreenConfig, configuration) :\n                                        $.extend(true, settings.defaultConfig.options, configuration);\n\n                            }\n                            $.extend(true, settings.currentConfig.options, configuration);\n                            settings.fotoramaApi.setOptions(settings.currentConfig.options);\n\n                            if (_.isNumber(index)) {\n                                $selectable.eq(index).trigger('focus');\n                            }\n                        }\n                    },\n\n                    /**\n                     * Updates gallery with specific set of items.\n                     * @param {Array.<Object>} data - Set of gallery items to update.\n                     */\n                    updateData: function (data) {\n                        var mainImageIndex;\n\n                        if (_.isArray(data)) {\n                            settings.fotoramaApi.load(data);\n                            mainImageIndex = getMainImageIndex(data);\n\n                            if (settings.fotoramaApi.activeIndex !== mainImageIndex) {\n                                settings.fotoramaApi.show({\n                                    index: mainImageIndex,\n                                    time: 0\n                                });\n                            }\n\n                            $.extend(false, settings, {\n                                data: data,\n                                defaultConfig: data\n                            });\n                            $.extend(false, config, {\n                                data: data\n                            });\n                        }\n                    },\n\n                    /**\n                     * Returns current images list\n                     *\n                     * @returns {Array}\n                     */\n                    returnCurrentImages: function () {\n                        var images = [];\n\n                        _.each(this.fotorama.data, function (item) {\n                            images.push(_.omit(item, '$navThumbFrame', '$navDotFrame', '$stageFrame', 'labelledby'));\n                        });\n\n                        return images;\n                    },\n\n                    /**\n                     * Updates gallery data partially by index\n                     * @param {Number} index - Index of image in data array to be updated.\n                     * @param {Object} item - Standart gallery image object.\n                     *\n                     */\n                    updateDataByIndex: function (index, item) {\n                        settings.fotoramaApi.spliceByIndex(index, item);\n                    }\n                };\n\n            settings.$element.data('gallery', api);\n            settings.api = settings.$element.data('gallery');\n            settings.$element.trigger('gallery:loaded');\n        }\n    });\n});\n","mage/msie/file-reader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery'\n], function ($) {\n    'use strict';\n\n    /**\n     * Init \"readAsBinaryString\" function for FileReader class.\n     * It need for IE11\n     * @param {Blob} fileData\n     */\n    var readAsBinaryStringIEFunc = function (fileData) {\n        var binary = '',\n            self = this,\n            reader = new FileReader();\n\n        /**\n         * Read file as binary string\n         */\n        reader.onload = function () {\n            var bytes, length, index;\n\n            /* eslint-disable no-undef */\n            bytes = new Uint8Array(reader.result);\n            /* eslint-enable */\n            length = bytes.length;\n\n            for (index = 0; index < length; index++) {\n                binary += String.fromCharCode(bytes[index]);\n            }\n            //self.result  - readonly so assign binary\n            self.content = binary;\n            $(self).trigger('onload');\n        };\n        reader.readAsArrayBuffer(fileData);\n    };\n\n    if (typeof FileReader.prototype.readAsBinaryString === 'undefined') {\n        FileReader.prototype.readAsBinaryString = readAsBinaryStringIEFunc;\n    }\n});\n","mage/apply/main.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery',\n    './scripts'\n], function (_, $, processScripts) {\n    'use strict';\n\n    var dataAttr = 'data-mage-init',\n        nodeSelector = '[' + dataAttr + ']';\n\n    /**\n     * Initializes components assigned to a specified element via data-* attribute.\n     *\n     * @param {HTMLElement} el - Element to initialize components with.\n     * @param {Object|String} config - Initial components' config.\n     * @param {String} component - Components' path.\n     */\n    function init(el, config, component) {\n        require([component], function (fn) {\n            var $el;\n\n            if (typeof fn === 'object') {\n                fn = fn[component].bind(fn);\n            }\n\n            if (_.isFunction(fn)) {\n                fn = fn.bind(null, config, el);\n            } else {\n                $el = $(el);\n\n                if ($el[component]) {\n                    // eslint-disable-next-line jquery-no-bind-unbind\n                    fn = $el[component].bind($el, config);\n                }\n            }\n            // Init module in separate task to prevent blocking main thread.\n            setTimeout(fn);\n        }, function (error) {\n            if ('console' in window && typeof window.console.error === 'function') {\n                console.error(error);\n            }\n\n            return true;\n        });\n    }\n\n    /**\n     * Parses elements 'data-mage-init' attribute as a valid JSON data.\n     * Note: data-mage-init attribute will be removed.\n     *\n     * @param {HTMLElement} el - Element whose attribute should be parsed.\n     * @returns {Object}\n     */\n    function getData(el) {\n        var data = el.getAttribute(dataAttr);\n\n        el.removeAttribute(dataAttr);\n\n        return {\n            el: el,\n            data: JSON.parse(data)\n        };\n    }\n\n    return {\n        /**\n         * Initializes components assigned to HTML elements via [data-mage-init].\n         *\n         * @example Sample 'data-mage-init' declaration.\n         *      data-mage-init='{\"path/to/component\": {\"foo\": \"bar\"}}'\n         */\n        apply: function (context) {\n            var virtuals = processScripts(!context ? document : context),\n                nodes = document.querySelectorAll(nodeSelector);\n\n            _.toArray(nodes)\n                .map(getData)\n                .concat(virtuals)\n                .forEach(function (itemContainer) {\n                    var element = itemContainer.el;\n\n                    _.each(itemContainer.data, function (obj, key) {\n                            if (obj.mixins) {\n                                require(obj.mixins, function () { //eslint-disable-line max-nested-callbacks\n                                    var i, len;\n\n                                    for (i = 0, len = arguments.length; i < len; i++) {\n                                        $.extend(\n                                            true,\n                                            itemContainer.data[key],\n                                            arguments[i](itemContainer.data[key], element)\n                                        );\n                                    }\n\n                                    delete obj.mixins;\n                                    init.call(null, element, obj, key);\n                                });\n                            } else {\n                                init.call(null, element, obj, key);\n                            }\n\n                        }\n                    );\n\n                });\n        },\n        applyFor: init\n    };\n});\n","mage/apply/scripts.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery'\n], function (_, $) {\n    'use strict';\n\n    var scriptSelector = 'script[type=\"text/x-magento-init\"]',\n        dataAttr = 'data-mage-init',\n        virtuals = [];\n\n    /**\n     * Adds components to the virtual list.\n     *\n     * @param {Object} components\n     */\n    function addVirtual(components) {\n        virtuals.push({\n            el: false,\n            data: components\n        });\n    }\n\n    /**\n     * Merges provided data with a current data\n     * of a elements' \"data-mage-init\" attribute.\n     *\n     * @param {Object} components - Object with components and theirs configuration.\n     * @param {HTMLElement} elem - Element whose data should be modified.\n     */\n    function setData(components, elem) {\n        var data = elem.getAttribute(dataAttr);\n\n        data = data ? JSON.parse(data) : {};\n        _.each(components, function (obj, key) {\n            if (_.has(obj, 'mixins')) {\n                data[key] = data[key] || {};\n                data[key].mixins = data[key].mixins || [];\n                data[key].mixins = data[key].mixins.concat(obj.mixins);\n                delete obj.mixins;\n            }\n        });\n\n        data = $.extend(true, data, components);\n        data = JSON.stringify(data);\n        elem.setAttribute(dataAttr, data);\n    }\n\n    /**\n     * Search for the elements by privded selector and extends theirs data.\n     *\n     * @param {Object} components - Object with components and theirs configuration.\n     * @param {String} selector - Selector for the elements.\n     */\n    function processElems(components, selector) {\n        var elems,\n            iterator;\n\n        if (selector === '*') {\n            addVirtual(components);\n\n            return;\n        }\n\n        elems = document.querySelectorAll(selector);\n        iterator = setData.bind(null, components);\n\n        _.toArray(elems).forEach(iterator);\n    }\n\n    /**\n     * Parses content of a provided script node.\n     * Note: node will be removed from DOM.\n     *\n     * @param {HTMLScriptElement} node - Node to be processed.\n     * @returns {Object}\n     */\n    function getNodeData(node) {\n        var data = node.textContent;\n\n        node.parentNode.removeChild(node);\n\n        return JSON.parse(data);\n    }\n\n    /**\n     * Parses 'script' tags with a custom type attribute and moves it's data\n     * to a 'data-mage-init' attribute of an element found by provided selector.\n     * Note: All found script nodes will be removed from DOM.\n     *\n     * @returns {Array} An array of components not assigned to the specific element.\n     *\n     * @example Sample declaration.\n     *      <script type=\"text/x-magento-init\">\n     *          {\n     *              \"body\": {\n     *                  \"path/to/component\": {\"foo\": \"bar\"}\n     *              }\n     *          }\n     *      </script>\n     *\n     * @example Providing data without selector.\n     *      {\n     *          \"*\": {\n     *              \"path/to/component\": {\"bar\": \"baz\"}\n     *          }\n     *      }\n     */\n    return function () {\n        var nodes = document.querySelectorAll(scriptSelector);\n\n        _.toArray(nodes)\n            .map(getNodeData)\n            .forEach(function (item) {\n                _.each(item, processElems);\n            });\n\n        return virtuals.splice(0, virtuals.length);\n    };\n});\n","mage/validation/validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/validation',\n    'mage/translate'\n], function ($) {\n    'use strict';\n\n    $.each({\n        'validate-grouped-qty': [\n            function (value, element, params) {\n                var result = false,\n                    total = 0;\n\n                $(params).find('input[data-validate*=\"validate-grouped-qty\"]').each(function (i, e) {\n                    var val = $(e).val(),\n                        valInt;\n\n                    if (val && val.length > 0) {\n                        result = true;\n                        valInt = parseFloat(val) || 0;\n\n                        if (valInt >= 0) {\n                            total += valInt;\n                        } else {\n                            result = false;\n\n                            return result;\n                        }\n                    }\n                });\n\n                return result && total > 0;\n            },\n            $.mage.__('Please specify the quantity of product(s).')\n        ],\n        'validate-one-checkbox-required-by-name': [\n            function (value, element, params) {\n                var checkedCount = 0,\n                    container;\n\n                if (element.type === 'checkbox') {\n                    $('[name=\"' + element.name + '\"]').each(\n                        function () {\n                            if ($(this).is(':checked')) {\n                                checkedCount += 1;\n\n                                return false;\n                            }\n                        }\n                    );\n                }\n                container = '#' + params;\n\n                if (checkedCount > 0) {\n                    $(container).removeClass('validation-failed');\n                    $(container).addClass('validation-passed');\n\n                    return true;\n                }\n                $(container).addClass('validation-failed');\n                $(container).removeClass('validation-passed');\n\n                return false;\n            },\n            $.mage.__('Please select one of the options.')\n        ],\n        'validate-date-between': [\n            function (value, element, params) {\n                var minDate = new Date(params[0]),\n                    maxDate = new Date(params[1]),\n                    inputDate = new Date(element.value),\n                    message;\n\n                minDate.setHours(0);\n                maxDate.setHours(0);\n\n                if (inputDate >= minDate && inputDate <= maxDate) {\n                    return true;\n                }\n                message = $.mage.__('Please enter a date between %min and %max.');\n                this.dateBetweenErrorMessage = message.replace('%min', minDate).replace('%max', maxDate);\n\n                return false;\n            },\n            function () {\n                return this.dateBetweenErrorMessage;\n            }\n        ],\n        'validate-dob': [\n            function (val, element, params) {\n                var dob = $(element).parents('.customer-dob'),\n                    dayVal, monthVal, yearVal, dobLength, day, month, year, curYear,\n                    validYearMessage, validateDayInMonth, validDateMessage, today, dateEntered;\n\n                $(dob).find('.' + this.settings.errorClass).removeClass(this.settings.errorClass);\n                dayVal = $(dob).find(params[0]).find('input:text').val();\n                monthVal = $(dob).find(params[1]).find('input:text').val();\n                yearVal = $(dob).find(params[2]).find('input:text').val();\n                dobLength = dayVal.length + monthVal.length + yearVal.length;\n\n                if (params[3] && dobLength === 0) {\n                    this.dobErrorMessage = $.mage.__('This is a required field.');\n\n                    return false;\n                }\n\n                if (!params[3] && dobLength === 0) {\n                    return true;\n                }\n                day = parseInt(dayVal, 10) || 0;\n                month = parseInt(monthVal, 10) || 0;\n                year = parseInt(yearVal, 10) || 0;\n                curYear = new Date().getFullYear();\n\n                if (!day || !month || !year) {\n                    this.dobErrorMessage = $.mage.__('Please enter a valid full date.');\n\n                    return false;\n                }\n\n                if (month < 1 || month > 12) {\n                    this.dobErrorMessage = $.mage.__('Please enter a valid month (1-12).');\n\n                    return false;\n                }\n\n                if (year < 1900 || year > curYear) {\n                    validYearMessage = $.mage.__('Please enter a valid year (1900-%1).');\n                    this.dobErrorMessage = validYearMessage.replace('%1', curYear.toString());\n\n                    return false;\n                }\n                validateDayInMonth = new Date(year, month, 0).getDate();\n\n                if (day < 1 || day > validateDayInMonth) {\n                    validDateMessage = $.mage.__('Please enter a valid day (1-%1).');\n                    this.dobErrorMessage = validDateMessage.replace('%1', validateDayInMonth.toString());\n\n                    return false;\n                }\n                today = new Date();\n                dateEntered = new Date();\n                dateEntered.setFullYear(year, month - 1, day);\n\n                if (dateEntered > today) {\n                    this.dobErrorMessage = $.mage.__('Please enter a date from the past.');\n\n                    return false;\n                }\n\n                day = day % 10 === day ? '0' + day : day;\n                month = month % 10 === month ? '0' + month : month;\n                $(element).val(month + '/' + day + '/' + year);\n\n                return true;\n            },\n            function () {\n                return this.dobErrorMessage;\n            }\n        ]\n    }, function (i, rule) {\n        rule.unshift(i);\n        $.validator.addMethod.apply($.validator, rule);\n    });\n});\n","mage/validation/url.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n\n        /**\n         * Redirects to the url if it is considered safe\n         *\n         * @param {String} path - url to be redirected to\n         */\n        redirect: function (path) {\n            path = this.sanitize(path);\n\n            if (this.validate(path)) {\n                window.location.href = path;\n            }\n        },\n\n        /**\n         * Validates url\n         *\n         * @param {Object} path - url to be validated\n         * @returns {Boolean}\n         */\n        validate: function (path) {\n            var hostname = window.location.hostname;\n\n            if (path.indexOf(hostname) === -1 ||\n                path.indexOf('javascript:') !== -1 ||\n                path.indexOf('vbscript:') !== -1) {\n                return false;\n            }\n\n            return true;\n        },\n\n        /**\n         * Sanitize url, replacing disallowed chars\n         *\n         * @param {String} path - url to be normalized\n         * @returns {String}\n         */\n        sanitize: function (path) {\n            return path.replace('[^-A-Za-z0-9+&@#/%?=~_|!:,.;\\(\\)]', '');\n        }\n    };\n});\n","mage/utils/wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * Utility methods used to wrap and extend functions.\n *\n * @example Usage of a 'wrap' method with arguments delegation.\n *      var multiply = function (a, b) {\n *          return a * b;\n *      };\n *\n *      multiply = module.wrap(multiply, function (orig) {\n *          return 'Result is: ' + orig();\n *      });\n *\n *      multiply(2, 2);\n *      => 'Result is: 4'\n *\n * @example Usage of 'wrapSuper' method.\n *      var multiply = function (a, b) {\n *         return a * b;\n *      };\n *\n *      var obj = {\n *          multiply: module.wrapSuper(multiply, function () {\n *              return 'Result is: ' + this._super();\n *          });\n *      };\n *\n *      obj.multiply(2, 2);\n *      => 'Result is: 4'\n */\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    /**\n     * Checks if string has a '_super' substring.\n     */\n    var superReg = /\\b_super\\b/;\n\n    return {\n\n        /**\n         * Wraps target function with a specified wrapper, which will receive\n         * reference to the original function as a first argument.\n         *\n         * @param {Function} target - Function to be wrapped.\n         * @param {Function} wrapper - Wrapper function.\n         * @returns {Function} Wrapper function.\n         */\n        wrap: function (target, wrapper) {\n            if (!_.isFunction(target) || !_.isFunction(wrapper)) {\n                return wrapper;\n            }\n\n            return function () {\n                var args    = _.toArray(arguments),\n                    ctx     = this,\n                    _super;\n\n                /**\n                 * Function that will be passed to the wrapper.\n                 * If no arguments will be passed to it, then the original\n                 * function will be called with an arguments of a wrapper function.\n                 */\n                _super = function () {\n                    var superArgs = arguments.length ? arguments : args.slice(1);\n\n                    return target.apply(ctx, superArgs);\n                };\n\n                args.unshift(_super);\n\n                return wrapper.apply(ctx, args);\n            };\n        },\n\n        /**\n         * Wraps the incoming function to implement support of the '_super' method.\n         *\n         * @param {Function} target - Function to be wrapped.\n         * @param {Function} wrapper - Wrapper function.\n         * @returns {Function} Wrapped function.\n         */\n        wrapSuper: function (target, wrapper) {\n            if (!this.hasSuper(wrapper) || !_.isFunction(target)) {\n                return wrapper;\n            }\n\n            return function () {\n                var _super  = this._super,\n                    args    = arguments,\n                    result;\n\n                /**\n                 * Temporary define '_super' method which\n                 * contains call to the original function.\n                 */\n                this._super = function () {\n                    var superArgs = arguments.length ? arguments : args;\n\n                    return target.apply(this, superArgs);\n                };\n\n                result = wrapper.apply(this, args);\n\n                this._super = _super;\n\n                return result;\n            };\n        },\n\n        /**\n         * Checks wether the incoming method contains calls of the '_super' method.\n         *\n         * @param {Function} fn - Function to be checked.\n         * @returns {Boolean}\n         */\n        hasSuper: function (fn) {\n            return _.isFunction(fn) && superReg.test(fn);\n        },\n\n        /**\n         * Extends target object with provided extenders.\n         * If property in target and extender objects is a function,\n         * then it will be wrapped using 'wrap' method.\n         *\n         * @param {Object} target - Object to be extended.\n         * @param {...Object} extenders - Multiple extenders objects.\n         * @returns {Object} Modified target object.\n         */\n        extend: function (target) {\n            var extenders = _.toArray(arguments).slice(1),\n                iterator = this._extend.bind(this, target);\n\n            extenders.forEach(iterator);\n\n            return target;\n        },\n\n        /**\n         * Same as the 'extend' method, but operates only on one extender object.\n         *\n         * @private\n         * @param {Object} target\n         * @param {Object} extender\n         */\n        _extend: function (target, extender) {\n            _.each(extender, function (value, key) {\n                target[key] = this.wrap(target[key], extender[key]);\n            }, this);\n        }\n    };\n});\n","mage/utils/misc.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'jquery',\n    'mage/utils/objects'\n], function (_, $, utils) {\n    'use strict';\n\n    var defaultAttributes,\n        ajaxSettings,\n        map;\n\n    defaultAttributes = {\n        method: 'post',\n        enctype: 'multipart/form-data'\n    };\n\n    ajaxSettings = {\n        default: {\n            method: 'POST',\n            cache: false,\n            processData: false,\n            contentType: false\n        },\n        simple: {\n            method: 'POST',\n            dataType: 'json'\n        }\n    };\n\n    map = {\n        'D': 'DDD',\n        'dd': 'DD',\n        'd': 'D',\n        'EEEE': 'dddd',\n        'EEE': 'ddd',\n        'e': 'd',\n        'yyyy': 'YYYY',\n        'yy': 'YY',\n        'y': 'YYYY',\n        'a': 'A'\n    };\n\n    return {\n\n        /**\n         * Generates a unique identifier.\n         *\n         * @param {Number} [size=7] - Length of a resulting identifier.\n         * @returns {String}\n         */\n        uniqueid: function (size) {\n            var code = Math.random() * 25 + 65 | 0,\n                idstr = String.fromCharCode(code);\n\n            size = size || 7;\n\n            while (idstr.length < size) {\n                code = Math.floor(Math.random() * 42 + 48);\n\n                if (code < 58 || code > 64) {\n                    idstr += String.fromCharCode(code);\n                }\n            }\n\n            return idstr;\n        },\n\n        /**\n         * Limits function call.\n         *\n         * @param {Object} owner\n         * @param {String} target\n         * @param {Number} limit\n         */\n        limit: function (owner, target, limit) {\n            var fn = owner[target];\n\n            owner[target] = _.debounce(fn.bind(owner), limit);\n        },\n\n        /**\n         * Converts mage date format to a moment.js format.\n         *\n         * @param {String} mageFormat\n         * @returns {String}\n         */\n        normalizeDate: function (mageFormat) {\n            var result = mageFormat;\n\n            _.each(map, function (moment, mage) {\n                result = result.replace(\n                    new RegExp(mage + '(?=([^\\u0027]*\\u0027[^\\u0027]*\\u0027)*[^\\u0027]*$)'),\n                    moment\n                );\n            });\n            result = result.replace(/'(.*?)'/g, '[$1]');\n            return result;\n        },\n\n        /**\n         * Puts provided value in range of min and max parameters.\n         *\n         * @param {Number} value - Value to be located.\n         * @param {Number} min - Min value.\n         * @param {Number} max - Max value.\n         * @returns {Number}\n         */\n        inRange: function (value, min, max) {\n            return Math.min(Math.max(min, value), max);\n        },\n\n        /**\n         * Serializes and sends data via POST request.\n         *\n         * @param {Object} options - Options object that consists of\n         *      a 'url' and 'data' properties.\n         * @param {Object} attrs - Attributes that will be added to virtual form.\n         */\n        submit: function (options, attrs) {\n            var form        = document.createElement('form'),\n                data        = utils.serialize(options.data),\n                attributes  = _.extend({}, defaultAttributes, attrs || {});\n\n            if (!attributes.action) {\n                attributes.action = options.url;\n            }\n\n            data['form_key'] = window.FORM_KEY;\n\n            _.each(attributes, function (value, name) {\n                form.setAttribute(name, value);\n            });\n\n            data = _.map(\n                data,\n                function (value, name) {\n                    return '<input type=\"hidden\" ' +\n                        'name=\"' + _.escape(name) + '\" ' +\n                        'value=\"' + _.escape(value) + '\"' +\n                        ' />';\n                }\n            ).join('');\n\n            form.insertAdjacentHTML('afterbegin', data);\n            document.body.appendChild(form);\n\n            form.submit();\n        },\n\n        /**\n         * Serializes and sends data via AJAX POST request.\n         *\n         * @param {Object} options - Options object that consists of\n         *      a 'url' and 'data' properties.\n         * @param {Object} config\n         */\n        ajaxSubmit: function (options, config) {\n            var t = new Date().getTime(),\n                settings;\n\n            options.data['form_key'] = window.FORM_KEY;\n            options.data = this.prepareFormData(options.data, config.ajaxSaveType);\n            settings = _.extend({}, ajaxSettings[config.ajaxSaveType], options || {});\n\n            if (!config.ignoreProcessEvents) {\n                $('body').trigger('processStart');\n            }\n\n            return $.ajax(settings)\n                .done(function (data) {\n                    if (config.response) {\n                        data.t = t;\n                        config.response.data(data);\n                        config.response.status(undefined);\n                        config.response.status(!data.error);\n                    }\n                })\n                .fail(function () {\n                    if (config.response) {\n                        config.response.status(undefined);\n                        config.response.status(false);\n                        config.response.data({\n                            error: true,\n                            messages: 'Something went wrong.',\n                            t: t\n                        });\n                    }\n                })\n                .always(function () {\n                    if (!config.ignoreProcessEvents) {\n                        $('body').trigger('processStop');\n                    }\n                });\n        },\n\n        /**\n         * Creates FormData object and append this data.\n         *\n         * @param {Object} data\n         * @param {String} type\n         * @returns {FormData}\n         */\n        prepareFormData: function (data, type) {\n            var formData;\n\n            if (type === 'default') {\n                formData = new FormData();\n                _.each(utils.serialize(data), function (val, name) {\n                    formData.append(name, val);\n                });\n            } else if (type === 'simple') {\n                formData = utils.serialize(data);\n            }\n\n            return formData;\n        },\n\n        /**\n         * Filters data object. Finds properties with suffix\n         * and sets their values to properties with the same name without suffix.\n         *\n         * @param {Object} data - The data object that should be filtered\n         * @param {String} suffix - The string by which data object should be filtered\n         * @param {String} separator - The string that is separator between property and suffix\n         *\n         * @returns {Object} Filtered data object\n         */\n        filterFormData: function (data, suffix, separator) {\n            data = data || {};\n            suffix = suffix || 'prepared-for-send';\n            separator = separator || '-';\n\n            _.each(data, function (value, key) {\n                if (_.isObject(value) && !Array.isArray(value)) {\n                    this.filterFormData(value, suffix, separator);\n                } else if (_.isString(key) && ~key.indexOf(suffix)) {\n                    data[key.split(separator)[0]] = value;\n                    delete data[key];\n                }\n            }, this);\n\n            return data;\n        },\n\n        /**\n         * Replaces special characters with their corresponding HTML entities.\n         *\n         * @param {String} string - Text to escape.\n         * @returns {String} Escaped text.\n         */\n        escape: function (string) {\n            return string ? $('<p></p>').text(string).html().replace(/\"/g, '&quot;') : string;\n        },\n\n        /**\n         * Replaces symbol codes with their unescaped counterparts.\n         *\n         * @param {String} data\n         *\n         * @returns {String}\n         */\n        unescape: function (data) {\n            var unescaped = _.unescape(data),\n                mapCharacters = {\n                    '&#039;': '\\''\n                };\n\n            _.each(mapCharacters, function (value, key) {\n                unescaped = unescaped.replace(key, value);\n            });\n\n            return unescaped;\n        },\n\n        /**\n         * Converts PHP IntlFormatter format to moment format.\n         *\n         * @param {String} format - PHP format\n         * @returns {String} - moment compatible formatting\n         */\n        convertToMomentFormat: function (format) {\n            var newFormat;\n\n            newFormat = format.replace(/yyyy|yy|y/, 'YYYY'); // replace the year\n            newFormat = newFormat.replace(/dd|d/g, 'DD'); // replace the date\n\n            return newFormat;\n        },\n\n        /**\n         * Get Url Parameters.\n         *\n         * @param {String} url - Url string\n         * @returns {Object}\n         */\n        getUrlParameters: function (url) {\n            var params = {},\n                queries = url.split('?'),\n                temp,\n                i,\n                l;\n\n            if (!queries[1]) {\n                return params;\n            }\n\n            queries = queries[1].split('&');\n\n            for (i = 0, l = queries.length; i < l; i++) {\n                temp = queries[i].split('=');\n\n                if (temp[1]) {\n                    params[temp[0]] = decodeURIComponent(temp[1].replace(/\\+/g, '%20'));\n                } else {\n                    params[temp[0]] = '';\n                }\n            }\n\n            return params;\n        }\n    };\n});\n","mage/utils/main.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(function (require) {\n    'use strict';\n\n    var utils = {},\n        _ = require('underscore'),\n        root = typeof self == 'object' && self.self === self && self ||\n            typeof global == 'object' && global.global === global && global ||\n            Function('return this')() || {};\n\n    root._ = _;\n\n    return _.extend(\n        utils,\n        require('./arrays'),\n        require('./compare'),\n        require('./misc'),\n        require('./objects'),\n        require('./strings'),\n        require('./template')\n    );\n});\n","mage/utils/template.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* eslint-disable no-shadow */\n\ndefine([\n    'jquery',\n    'underscore',\n    'mage/utils/objects',\n    'mage/utils/strings'\n], function ($, _, utils, stringUtils) {\n    'use strict';\n\n    var tmplSettings = _.templateSettings,\n        interpolate = /\\$\\{([\\s\\S]+?)\\}/g,\n        opener = '${',\n        template,\n        hasStringTmpls;\n\n    /**\n     * Identifies whether ES6 templates are supported.\n     */\n    hasStringTmpls = (function () {\n        var testString = 'var foo = \"bar\"; return `${ foo }` === foo';\n\n        try {\n            return Function(testString)();\n        } catch (e) {\n            return false;\n        }\n    })();\n\n    /**\n     * Objects can specify how to use templating for their properties - getting that configuration.\n     *\n     * To disable rendering for all properties of your object add __disableTmpl: true.\n     * To disable for specific property add __disableTmpl: {propertyName: true}.\n     * To limit recursion for a specific property add __disableTmpl: {propertyName: numberOfCycles}.\n     *\n     * @param {String} tmpl\n     * @param {Object | undefined} target\n     * @returns {Boolean|Object}\n     */\n    function isTmplIgnored(tmpl, target) {\n        var parsedTmpl;\n\n        try {\n            parsedTmpl = JSON.parse(tmpl);\n\n            if (typeof parsedTmpl === 'object') {\n                return tmpl.includes('__disableTmpl');\n            }\n        } catch (e) {\n        }\n\n        if (typeof target !== 'undefined') {\n            if (typeof target === 'object' && target.hasOwnProperty('__disableTmpl')) {\n                return target.__disableTmpl;\n            }\n        }\n\n        return false;\n\n    }\n\n    if (hasStringTmpls) {\n\n        /*eslint-disable no-unused-vars, no-eval*/\n        /**\n         * Evaluates template string using ES6 templates.\n         *\n         * @param {String} tmpl - Template string.\n         * @param {Object} $ - Data object used in a template.\n         * @returns {String} Compiled template.\n         */\n        template = function (tmpl, $) {\n            return eval('`' + tmpl + '`');\n        };\n\n        /*eslint-enable no-unused-vars, no-eval*/\n    } else {\n\n        /**\n         * Fallback function used when ES6 templates are not supported.\n         * Uses underscore templates renderer.\n         *\n         * @param {String} tmpl - Template string.\n         * @param {Object} data - Data object used in a template.\n         * @returns {String} Compiled template.\n         */\n        template = function (tmpl, data) {\n            var cached = tmplSettings.interpolate;\n\n            tmplSettings.interpolate = interpolate;\n\n            tmpl = _.template(tmpl, {\n                variable: '$'\n            })(data);\n\n            tmplSettings.interpolate = cached;\n\n            return tmpl;\n        };\n    }\n\n    /**\n     * Checks if provided value contains template syntax.\n     *\n     * @param {*} value - Value to be checked.\n     * @returns {Boolean}\n     */\n    function isTemplate(value) {\n        return typeof value === 'string' &&\n            value.indexOf(opener) !== -1 &&\n            // the below pattern almost always indicates an accident which should not cause template evaluation\n            // refuse to evaluate\n            value.indexOf('${{') === -1;\n    }\n\n    /**\n     * Iteratively processes provided string\n     * until no templates syntax will be found.\n     *\n     * @param {String} tmpl - Template string.\n     * @param {Object} data - Data object used in a template.\n     * @param {Boolean} [castString=false] - Flag that indicates whether template\n     *      should be casted after evaluation to a value of another type or\n     *      that it should be leaved as a string.\n     * @param {Number|undefined} maxCycles - Maximum number of rendering cycles, can be 0.\n     * @returns {*} Compiled template.\n     */\n    function render(tmpl, data, castString, maxCycles) {\n        var last = tmpl,\n            cycles = 0;\n\n        while (~tmpl.indexOf(opener) && (typeof maxCycles === 'undefined' || cycles < maxCycles)) {\n            if (!isTmplIgnored(tmpl)) {\n                tmpl = template(tmpl, data);\n            }\n\n            if (tmpl === last) {\n                break;\n            }\n\n            last = tmpl;\n            cycles++;\n        }\n\n        return castString ?\n            stringUtils.castString(tmpl) :\n            tmpl;\n    }\n\n    return {\n\n        /**\n         * Applies provided data to the template.\n         *\n         * @param {Object|String} tmpl\n         * @param {Object} [data] - Data object to match with template.\n         * @param {Boolean} [castString=false] - Flag that indicates whether template\n         *      should be casted after evaluation to a value of another type or\n         *      that it should be leaved as a string.\n         * @returns {*}\n         *\n         * @example Template defined as a string.\n         *      var source = { foo: 'Random Stuff', bar: 'Some' };\n         *\n         *      utils.template('${ $.bar } ${ $.foo }', source);\n         *      => 'Some Random Stuff';\n         *\n         * @example Template defined as an object.\n         *      var tmpl = {\n         *              key: {'${ $.$data.bar }': '${ $.$data.foo }'},\n         *              foo: 'bar',\n         *              x1: 2, x2: 5,\n         *              delta: '${ $.x2 - $.x1 }',\n         *              baz: 'Upper ${ $.foo.toUpperCase() }'\n         *      };\n         *\n         *      utils.template(tmpl, source);\n         *      => {\n         *          key: {'Some': 'Random Stuff'},\n         *          foo: 'bar',\n         *          x1: 2, x2: 5,\n         *          delta: 3,\n         *          baz: 'Upper BAR'\n         *      };\n         */\n        template: function (tmpl, data, castString, dontClone) {\n            if (typeof tmpl === 'string') {\n                return render(tmpl, data, castString);\n            }\n\n            if (!dontClone) {\n                tmpl = utils.copy(tmpl);\n            }\n\n            tmpl.$data = data || {};\n\n            /**\n             * Template iterator function.\n             */\n            _.each(tmpl, function iterate(value, key, list) {\n                var disabled,\n                    maxCycles;\n\n                if (key === '$data') {\n                    return;\n                }\n\n                if (isTemplate(key)) {\n                    delete list[key];\n\n                    key = render(key, tmpl);\n                    list[key] = value;\n                }\n\n                if (isTemplate(value)) {\n                    //Getting template disabling settings, can be true for all disabled and separate settings\n                    //for each property.\n                    disabled = isTmplIgnored(value, list);\n\n                    if (typeof disabled === 'object' && disabled.hasOwnProperty(key) && disabled[key] !== false) {\n                        //Checking if specific settings for a property provided.\n                        maxCycles = disabled[key];\n                    }\n\n                    if (disabled === true || maxCycles === true) {\n                        //Rendering for all properties is disabled.\n                        maxCycles = 0;\n                    }\n\n                    list[key] = render(value, tmpl, castString, maxCycles);\n                } else if ($.isPlainObject(value) || Array.isArray(value)) {\n                    _.each(value, iterate);\n                }\n            });\n\n            delete tmpl.$data;\n\n            return tmpl;\n        }\n    };\n});\n","mage/utils/compare.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore',\n    'mage/utils/objects'\n], function (_, utils) {\n    'use strict';\n\n    var result = [];\n\n    /**\n     * Checks if all of the provided arrays contains equal values.\n     *\n     * @param {(Boolean|Array)} [keepOrder=false]\n     * @param {Array} target\n     * @returns {Boolean}\n     */\n    function equalArrays(keepOrder, target) {\n        var args = _.toArray(arguments),\n            arrays;\n\n        if (!Array.isArray(keepOrder)) {\n            arrays      = args.slice(2);\n        } else {\n            target      = keepOrder;\n            keepOrder   = false;\n            arrays      = args.slice(1);\n        }\n\n        if (!arrays.length) {\n            return true;\n        }\n\n        return arrays.every(function (array) {\n            if (array === target) {\n                return true;\n            } else if (array.length !== target.length) {\n                return false;\n            } else if (!keepOrder) {\n                return !_.difference(target, array).length;\n            }\n\n            return array.every(function (value, index) {\n                return target[index] === value;\n            });\n        });\n    }\n\n    /**\n     * Checks if two values are different.\n     *\n     * @param {*} a - First value.\n     * @param {*} b - Second value.\n     * @returns {Boolean}\n     */\n    function isDifferent(a, b) {\n        var oldIsPrimitive = utils.isPrimitive(a);\n\n        if (Array.isArray(a) && Array.isArray(b)) {\n            return !equalArrays(true, a, b);\n        }\n\n        return oldIsPrimitive ? a !== b : true;\n    }\n\n    /**\n     * @param {String} prefix\n     * @param {String} part\n     */\n    function getPath(prefix, part) {\n        return prefix ? prefix + '.' + part : part;\n    }\n\n    /**\n     * Checks if object has own specified property.\n     *\n     * @param {*} obj - Value to be checked.\n     * @param {String} key - Key of the property.\n     * @returns {Boolean}\n     */\n    function hasOwn(obj, key) {\n        return Object.prototype.hasOwnProperty.call(obj, key);\n    }\n\n    /**\n     * @param {Array} changes\n     */\n    function getContainers(changes) {\n        var containers  = {},\n            indexed     = _.indexBy(changes, 'path');\n\n        _.each(indexed, function (change, name) {\n            var path;\n\n            name.split('.').forEach(function (part) {\n                path = getPath(path, part);\n\n                if (path in indexed) {\n                    return;\n                }\n\n                (containers[path] = containers[path] || []).push(change);\n            });\n        });\n\n        return containers;\n    }\n\n    /**\n     * @param {String} path\n     * @param {String} name\n     * @param {String} type\n     * @param {String} newValue\n     * @param {String} oldValue\n     */\n    function addChange(path, name, type, newValue, oldValue) {\n        var data;\n\n        data = {\n            path: path,\n            name: name,\n            type: type\n        };\n\n        if (type !== 'remove') {\n            data.value = newValue;\n            data.oldValue = oldValue;\n        } else {\n            data.oldValue = newValue;\n        }\n\n        result.push(data);\n    }\n\n    /**\n     * @param {String} ns\n     * @param {String} name\n     * @param {String} type\n     * @param {String} iterator\n     * @param {String} placeholder\n     */\n    function setAll(ns, name, type, iterator, placeholder) {\n        var key;\n\n        if (arguments.length > 4) {\n            type === 'add' ?\n                addChange(ns, name, 'update', iterator, placeholder) :\n                addChange(ns, name, 'update', placeholder, iterator);\n        } else {\n            addChange(ns, name, type, iterator);\n        }\n\n        if (!utils.isObject(iterator)) {\n            return;\n        }\n\n        for (key in iterator) {\n            if (hasOwn(iterator, key)) {\n                setAll(getPath(ns, key), key, type, iterator[key]);\n            }\n        }\n    }\n\n    /*eslint-disable max-depth*/\n    /**\n     * @param {Object} old\n     * @param {Object} current\n     * @param {String} ns\n     * @param {String} name\n     */\n    function compare(old, current, ns, name) {\n        var key,\n            oldIsObj = utils.isObject(old),\n            newIsObj = utils.isObject(current);\n\n        if (oldIsObj && newIsObj) {\n            for (key in old) {\n                if (hasOwn(old, key) && !hasOwn(current, key)) {\n                    setAll(getPath(ns, key), key, 'remove', old[key]);\n                }\n            }\n\n            for (key in current) {\n                if (hasOwn(current, key)) {\n                    hasOwn(old, key) ?\n                        compare(old[key], current[key], getPath(ns, key), key) :\n                        setAll(getPath(ns, key), key, 'add', current[key]);\n                }\n            }\n        } else if (oldIsObj) {\n            setAll(ns, name, 'remove', old, current);\n        } else if (newIsObj) {\n            setAll(ns, name, 'add', current, old);\n        } else if (isDifferent(old, current)) {\n            addChange(ns, name, 'update', current, old);\n        }\n    }\n\n    /*eslint-enable max-depth*/\n\n    return {\n\n        /**\n         *\n         * @returns {Object}\n         */\n        compare: function () {\n            var changes;\n\n            compare.apply(null, arguments);\n\n            changes = result.splice(0);\n\n            return {\n                containers: getContainers(changes),\n                changes: changes,\n                equal: !changes.length\n            };\n        },\n\n        equalArrays: equalArrays\n    };\n});\n","mage/utils/objects.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'ko',\n    'jquery',\n    'underscore',\n    'mage/utils/strings'\n], function (ko, $, _, stringUtils) {\n    'use strict';\n\n    var primitives = [\n        'undefined',\n        'boolean',\n        'number',\n        'string'\n    ];\n\n    /**\n     * Sets nested property of a specified object.\n     * @private\n     *\n     * @param {Object} parent - Object to look inside for the properties.\n     * @param {Array} path - Splitted path the property.\n     * @param {*} value - Value of the last property in 'path' array.\n     * returns {*} New value for the property.\n     */\n    function setNested(parent, path, value) {\n        var last = path.pop(),\n            len = path.length,\n            pi = 0,\n            part = path[pi];\n\n        for (; pi < len; part = path[++pi]) {\n            if (!_.isObject(parent[part])) {\n                parent[part] = {};\n            }\n\n            parent = parent[part];\n        }\n\n        if (typeof parent[last] === 'function') {\n            parent[last](value);\n        } else {\n            parent[last] = value;\n        }\n\n        return value;\n    }\n\n    /**\n     * Retrieves value of a nested property.\n     * @private\n     *\n     * @param {Object} parent - Object to look inside for the properties.\n     * @param {Array} path - Splitted path the property.\n     * @returns {*} Value of the property.\n     */\n    function getNested(parent, path) {\n        var exists = true,\n            len = path.length,\n            pi = 0;\n\n        for (; pi < len && exists; pi++) {\n            parent = parent[path[pi]];\n\n            if (typeof parent === 'undefined') {\n                exists = false;\n            }\n        }\n\n        if (exists) {\n            if (ko.isObservable(parent)) {\n                parent = parent();\n            }\n\n            return parent;\n        }\n    }\n\n    /**\n     * Removes property from a specified object.\n     * @private\n     *\n     * @param {Object} parent - Object from which to remove property.\n     * @param {Array} path - Splitted path to the property.\n     */\n    function removeNested(parent, path) {\n        var field = path.pop();\n\n        parent = getNested(parent, path);\n\n        if (_.isObject(parent)) {\n            delete parent[field];\n        }\n    }\n\n    return {\n\n        /**\n         * Retrieves or defines objects' property by a composite path.\n         *\n         * @param {Object} data - Container for the properties specified in path.\n         * @param {String} path - Objects' properties divided by dots.\n         * @param {*} [value] - New value for the last property.\n         * @returns {*} Returns value of the last property in chain.\n         *\n         * @example\n         *      utils.nested({}, 'one.two', 3);\n         *      => { one: {two: 3} }\n         */\n        nested: function (data, path, value) {\n            var action = arguments.length > 2 ? setNested : getNested;\n\n            path = path ? path.split('.') : [];\n\n            return action(data, path, value);\n        },\n\n        /**\n         * Removes nested property from an object.\n         *\n         * @param {Object} data - Data source.\n         * @param {String} path - Path to the property e.g. 'one.two.three'\n         */\n        nestedRemove: function (data, path) {\n            path = path.split('.');\n\n            removeNested(data, path);\n        },\n\n        /**\n         * Flattens objects' nested properties.\n         *\n         * @param {Object} data - Object to flatten.\n         * @param {String} [separator='.'] - Objects' keys separator.\n         * @returns {Object} Flattened object.\n         *\n         * @example Example with a default separator.\n         *      utils.flatten({one: { two: { three: 'value'} }});\n         *      => { 'one.two.three': 'value' };\n         *\n         * @example Example with a custom separator.\n         *      utils.flatten({one: { two: { three: 'value'} }}, '=>');\n         *      => {'one=>two=>three': 'value'};\n         */\n        flatten: function (data, separator, parent, result) {\n            separator = separator || '.';\n            result = result || {};\n\n            if (!data) {\n                return result;\n            }\n\n            // UnderscoreJS each breaks when an object has a length property so we use Object.keys\n            _.each(Object.keys(data), function (name) {\n                var node = data[name];\n\n                if ({}.toString.call(node) === '[object Function]') {\n                    return;\n                }\n\n                if (parent) {\n                    name = parent + separator + name;\n                }\n\n                typeof node === 'object' ?\n                    this.flatten(node, separator, name, result) :\n                    result[name] = node;\n\n            }, this);\n\n            return result;\n        },\n\n        /**\n         * Opposite operation of the 'flatten' method.\n         *\n         * @param {Object} data - Previously flattened object.\n         * @param {String} [separator='.'] - Keys separator.\n         * @returns {Object} Object with nested properties.\n         *\n         * @example Example using custom separator.\n         *      utils.unflatten({'one=>two': 'value'}, '=>');\n         *      => {\n         *          one: { two: 'value' }\n         *      };\n         */\n        unflatten: function (data, separator) {\n            var result = {};\n\n            separator = separator || '.';\n\n            _.each(data, function (value, nodes) {\n                nodes = nodes.split(separator);\n\n                setNested(result, nodes, value);\n            });\n\n            return result;\n        },\n\n        /**\n         * Same operation as 'flatten' method,\n         * but returns objects' keys wrapped in '[]'.\n         *\n         * @param {Object} data - Object that should be serialized.\n         * @returns {Object} Serialized data.\n         *\n         * @example\n         *      utils.serialize({one: { two: { three: 'value'} }});\n         *      => { 'one[two][three]': 'value' }\n         */\n        serialize: function (data) {\n            var result = {};\n\n            data = this.flatten(data);\n\n            _.each(data, function (value, keys) {\n                keys = stringUtils.serializeName(keys);\n                value = _.isUndefined(value) ? '' : value;\n\n                result[keys] = value;\n            }, this);\n\n            return result;\n        },\n\n        /**\n         * Performs deep extend of specified objects.\n         *\n         * @returns {Object|Array} Extended object.\n         */\n        extend: function () {\n            var args = _.toArray(arguments);\n\n            args.unshift(true);\n\n            return $.extend.apply($, args);\n        },\n\n        /**\n         * Performs a deep clone of a specified object.\n         *\n         * @param {(Object|Array)} data - Data that should be copied.\n         * @returns {Object|Array} Cloned object.\n         */\n        copy: function (data) {\n            var result = data,\n                isArray = Array.isArray(data),\n                placeholder;\n\n            if (this.isObject(data) || isArray) {\n                placeholder = isArray ? [] : {};\n                result = this.extend(placeholder, data);\n            }\n\n            return result;\n        },\n\n        /**\n         * Performs a deep clone of a specified object.\n         * Doesn't save links to original object.\n         *\n         * @param {*} original - Object to clone\n         * @returns {*}\n         */\n        hardCopy: function (original) {\n            if (original === null || typeof original !== 'object') {\n                return original;\n            }\n\n            return JSON.parse(JSON.stringify(original));\n        },\n\n        /**\n         * Removes specified nested properties from the target object.\n         *\n         * @param {Object} target - Object whose properties should be removed.\n         * @param {(...String|Array|Object)} list - List that specifies properties to be removed.\n         * @returns {Object} Modified object.\n         *\n         * @example Basic usage\n         *      var obj = {a: {b: 2}, c: 'a'};\n         *\n         *      omit(obj, 'a.b');\n         *      => {'a.b': 2};\n         *      obj => {a: {}, c: 'a'};\n         *\n         * @example Various syntaxes that would return same result\n         *      omit(obj, ['a.b', 'c']);\n         *      omit(obj, 'a.b', 'c');\n         *      omit(obj, {'a.b': true, 'c': true});\n         */\n        omit: function (target, list) {\n            var removed = {},\n                ignored = list;\n\n            if (this.isObject(list)) {\n                ignored = [];\n\n                _.each(list, function (value, key) {\n                    if (value) {\n                        ignored.push(key);\n                    }\n                });\n            } else if (_.isString(list)) {\n                ignored = _.toArray(arguments).slice(1);\n            }\n\n            _.each(ignored, function (path) {\n                var value = this.nested(target, path);\n\n                if (!_.isUndefined(value)) {\n                    removed[path] = value;\n\n                    this.nestedRemove(target, path);\n                }\n            }, this);\n\n            return removed;\n        },\n\n        /**\n         * Checks if provided value is a plain object.\n         *\n         * @param {*} value - Value to be checked.\n         * @returns {Boolean}\n         */\n        isObject: function (value) {\n            var objProto = Object.prototype;\n\n            return typeof value == 'object' ?\n            objProto.toString.call(value) === '[object Object]' :\n                false;\n        },\n\n        /**\n         *\n         * @param {*} value\n         * @returns {Boolean}\n         */\n        isPrimitive: function (value) {\n            return value === null || ~primitives.indexOf(typeof value);\n        },\n\n        /**\n         * Iterates over obj props/array elems recursively, applying action to each one\n         *\n         * @param {Object|Array} data - Data to be iterated.\n         * @param {Function} action - Callback to be called with each item as an argument.\n         * @param {Number} [maxDepth=7] - Max recursion depth.\n         */\n        forEachRecursive: function (data, action, maxDepth) {\n            maxDepth = typeof maxDepth === 'number' && !isNaN(maxDepth) ? maxDepth - 1 : 7;\n\n            if (!_.isFunction(action) || _.isFunction(data) || maxDepth < 0) {\n                return;\n            }\n\n            if (!_.isObject(data)) {\n                action(data);\n\n                return;\n            }\n\n            _.each(data, function (value) {\n                this.forEachRecursive(value, action, maxDepth);\n            }, this);\n\n            action(data);\n        },\n\n        /**\n         * Maps obj props/array elems recursively\n         *\n         * @param {Object|Array} data - Data to be iterated.\n         * @param {Function} action - Callback to transform each item.\n         * @param {Number} [maxDepth=7] - Max recursion depth.\n         *\n         * @returns {Object|Array}\n         */\n        mapRecursive: function (data, action, maxDepth) {\n            var newData;\n\n            maxDepth = typeof maxDepth === 'number' && !isNaN(maxDepth) ? maxDepth - 1 : 7;\n\n            if (!_.isFunction(action) || _.isFunction(data) || maxDepth < 0) {\n                return data;\n            }\n\n            if (!_.isObject(data)) {\n                return action(data);\n            }\n\n            if (_.isArray(data)) {\n                newData = _.map(data, function (item) {\n                    return this.mapRecursive(item, action, maxDepth);\n                }, this);\n\n                return action(newData);\n            }\n\n            newData = _.mapObject(data, function (val, key) {\n                if (data.hasOwnProperty(key)) {\n                    return this.mapRecursive(val, action, maxDepth);\n                }\n\n                return val;\n            }, this);\n\n            return action(newData);\n        },\n\n        /**\n         * Removes empty(in common sence) obj props/array elems\n         *\n         * @param {*} data - Data to be cleaned.\n         * @returns {*}\n         */\n        removeEmptyValues: function (data) {\n            if (!_.isObject(data)) {\n                return data;\n            }\n\n            if (_.isArray(data)) {\n                return data.filter(function (item) {\n                    return !this.isEmptyObj(item);\n                }, this);\n            }\n\n            return _.omit(data, this.isEmptyObj.bind(this));\n        },\n\n        /**\n         * Checks that argument of any type is empty in common sence:\n         * empty string, string with spaces only, object without own props, empty array, null or undefined\n         *\n         * @param {*} val - Value to be checked.\n         * @returns {Boolean}\n         */\n        isEmptyObj: function (val) {\n\n            return _.isObject(val) && _.isEmpty(val) ||\n            this.isEmpty(val) ||\n            val && val.trim && this.isEmpty(val.trim());\n        }\n    };\n});\n\n","mage/utils/arrays.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    './strings'\n], function (_, utils) {\n    'use strict';\n\n    /**\n     * Defines index of an item in a specified container.\n     *\n     * @param {*} item - Item whose index should be defined.\n     * @param {Array} container - Container upon which to perform search.\n     * @returns {Number}\n     */\n    function getIndex(item, container) {\n        var index = container.indexOf(item);\n\n        if (~index) {\n            return index;\n        }\n\n        return _.findIndex(container, function (value) {\n            return value && value.name === item;\n        });\n    }\n\n    return {\n        /**\n         * Facade method to remove/add value from/to array\n         * without creating a new instance.\n         *\n         * @param {Array} arr - Array to be modified.\n         * @param {*} value - Value to add/remove.\n         * @param {Boolean} add - Flag that specfies operation.\n         * @returns {Utils} Chainable.\n         */\n        toggle: function (arr, value, add) {\n            return add ?\n                this.add(arr, value) :\n                this.remove(arr, value);\n        },\n\n        /**\n         * Removes the incoming value from array in case\n         * without creating a new instance of it.\n         *\n         * @param {Array} arr - Array to be modified.\n         * @param {*} value - Value to be removed.\n         * @returns {Utils} Chainable.\n         */\n        remove: function (arr, value) {\n            var index = arr.indexOf(value);\n\n            if (~index) {\n                arr.splice(index, 1);\n            }\n\n            return this;\n        },\n\n        /**\n         * Adds the incoming value to array if\n         * it's not alredy present in there.\n         *\n         * @param {Array} arr - Array to be modifed.\n         * @param {...*} arguments - Values to be added.\n         * @returns {Utils} Chainable.\n         */\n        add: function (arr) {\n            var values = _.toArray(arguments).slice(1);\n\n            values.forEach(function (value) {\n                if (!~arr.indexOf(value)) {\n                    arr.push(value);\n                }\n            });\n\n            return this;\n        },\n\n        /**\n         * Inserts specified item into container at a specified position.\n         *\n         * @param {*} item - Item to be inserted into container.\n         * @param {Array} container - Container of items.\n         * @param {*} [position=-1] - Position at which item should be inserted.\n         *      Position can represent:\n         *          - specific index in container\n         *          - item which might already be present in container\n         *          - structure with one of these properties: after, before\n         * @returns {Boolean|*}\n         *      - true if element has changed its' position\n         *      - false if nothing has changed\n         *      - inserted value if it wasn't present in container\n         */\n        insert: function (item, container, position) {\n            var currentIndex = getIndex(item, container),\n                newIndex,\n                target;\n\n            if (typeof position === 'undefined') {\n                position = -1;\n            } else if (typeof position === 'string') {\n                position = isNaN(+position) ? position : +position;\n            }\n\n            newIndex = position;\n\n            if (~currentIndex) {\n                target = container.splice(currentIndex, 1)[0];\n\n                if (typeof item === 'string') {\n                    item = target;\n                }\n            }\n\n            if (typeof position !== 'number') {\n                target = position.after || position.before || position;\n\n                newIndex = getIndex(target, container);\n\n                if (~newIndex && (position.after || newIndex >= currentIndex)) {\n                    newIndex++;\n                }\n            }\n\n            if (newIndex < 0) {\n                newIndex += container.length + 1;\n            }\n\n            container[newIndex] ?\n                container.splice(newIndex, 0, item) :\n                container[newIndex] = item;\n\n            return !~currentIndex ? item : currentIndex !== newIndex;\n        },\n\n        /**\n         * @param {Array} elems\n         * @param {Number} offset\n         * @return {Number|*}\n         */\n        formatOffset: function (elems, offset) {\n            if (utils.isEmpty(offset)) {\n                offset = -1;\n            }\n\n            offset = +offset;\n\n            if (offset < 0) {\n                offset += elems.length + 1;\n            }\n\n            return offset;\n        }\n    };\n});\n","mage/utils/strings.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'underscore'\n], function (_) {\n    'use strict';\n\n    var jsonRe = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/;\n\n    return {\n\n        /**\n         * Attempts to convert string to one of the primitive values,\n         * or to parse it as a valid json object.\n         *\n         * @param {String} str - String to be processed.\n         * @returns {*}\n         */\n        castString: function (str) {\n            try {\n                str = str === 'true' ? true :\n                    str === 'false' ? false :\n                        str === 'null' ? null :\n                            +str + '' === str ? +str :\n                                jsonRe.test(str) ? JSON.parse(str) :\n                                    str;\n            } catch (e) {\n            }\n\n            return str;\n        },\n\n        /**\n         * Splits string by separator if it's possible,\n         * otherwise returns the incoming value.\n         *\n         * @param {(String|Array|*)} str - String to split.\n         * @param {String} [separator=' '] - Seperator based on which to split the string.\n         * @returns {Array|*} Splitted string or the incoming value.\n         */\n        stringToArray: function (str, separator) {\n            separator = separator || ' ';\n\n            return typeof str === 'string' ?\n                str.split(separator) :\n                str;\n        },\n\n        /**\n         * Converts the incoming string which consists\n         * of a specified delimiters into a format commonly used in form elements.\n         *\n         * @param {String} name - The incoming string.\n         * @param {String} [separator='.']\n         * @returns {String} Serialized string.\n         *\n         * @example\n         *      utils.serializeName('one.two.three');\n         *      => 'one[two][three]';\n         */\n        serializeName: function (name, separator) {\n            var result;\n\n            separator = separator || '.';\n            name = name.split(separator);\n\n            result = name.shift();\n\n            name.forEach(function (part) {\n                result += '[' + part + ']';\n            });\n\n            return result;\n        },\n\n        /**\n         * Checks wether the incoming value is not empty,\n         * e.g. not 'null' or 'undefined'\n         *\n         * @param {*} value - Value to check.\n         * @returns {Boolean}\n         */\n        isEmpty: function (value) {\n            return value === '' || _.isUndefined(value) || _.isNull(value);\n        },\n\n        /**\n         * Adds 'prefix' to the 'part' value if it was provided.\n         *\n         * @param {String} prefix\n         * @param {String} part\n         * @returns {String}\n         */\n        fullPath: function (prefix, part) {\n            return prefix ? prefix + '.' + part : part;\n        },\n\n        /**\n         * Splits incoming string and returns its' part specified by offset.\n         *\n         * @param {String} parts\n         * @param {Number} [offset]\n         * @param {String} [delimiter=.]\n         * @returns {String}\n         */\n        getPart: function (parts, offset, delimiter) {\n            delimiter = delimiter || '.';\n            parts = parts.split(delimiter);\n            offset = this.formatOffset(parts, offset);\n\n            parts.splice(offset, 1);\n\n            return parts.join(delimiter) || '';\n        },\n\n        /**\n         * Converts nameThroughCamelCase to name-through-minus\n         *\n         * @param {String} string\n         * @returns {String}\n         */\n        camelCaseToMinus: function camelCaseToMinus(string) {\n            return ('' + string)\n                .split('')\n                .map(function (symbol, index) {\n                    return index ?\n                        symbol.toUpperCase() === symbol ?\n                        '-' + symbol.toLowerCase() :\n                            symbol :\n                        symbol.toLowerCase();\n                })\n                .join('');\n        },\n\n        /**\n         * Converts name-through-minus to nameThroughCamelCase\n         *\n         * @param {String} string\n         * @returns {String}\n         */\n        minusToCamelCase: function minusToCamelCase(string) {\n            return ('' + string)\n                .split('-')\n                .map(function (part, index) {\n                    return index ? part.charAt(0).toUpperCase() + part.slice(1) : part;\n                })\n                .join('');\n        }\n    };\n});\n","Magento_Variable/js/grid/columns/radioselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'underscore',\n    'mage/translate',\n    'Magento_Ui/js/grid/columns/column',\n    'jquery'\n], function (_, $t, Column, jQuery) {\n    'use strict';\n\n    return Column.extend({\n        defaults: {\n            bodyTmpl: 'Magento_Variable/grid/cells/radioselect',\n            draggable: false,\n            sortable: false,\n            selectedVariableCode: null,\n            selectedVariableType: null\n        },\n\n        /**\n         * Calls 'initObservable' of parent\n         *\n         * @returns {Object} Chainable.\n         */\n        initObservable: function () {\n            this._super().observe(['selectedVariableCode']);\n\n            return this;\n        },\n\n        /**\n         * Remove disable class from Insert Variable button after Variable has been chosen.\n         *\n         * @return {Boolean}\n         */\n        selectVariable: function () {\n            if (jQuery('#insert_variable').hasClass('disabled')) {\n                jQuery('#insert_variable').removeClass('disabled');\n            }\n\n            return true;\n        }\n    });\n});\n","Magento_Csp/js/sri.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\nrequire.config({\n    onNodeCreated: function (node, config, moduleName, url) {\n        'use strict';\n        if ('sriHashes' in window && url in window.sriHashes) {\n            node.setAttribute('integrity', window.sriHashes[url]);\n            node.setAttribute('crossorigin', 'anonymous');\n        }\n    }\n});\n","Amasty_Base/js/http_build_query.js":"/**\n * PHP htp_build_query() analog\n */\ndefine(\n    [],\n    function () {\n        'use strict';\n\n        /**\n         * Encodes param according to RFC3986 standard.\n         *\n         * @param {string} str\n         * @returns {string}\n         */\n        function encodeComponentRaw(str)\n        {\n            str = (str + '');\n            return encodeURIComponent(str)\n                .replace(/!/g, '%21')\n                .replace(/'/g, '%27')\n                .replace(/\\(/g, '%28')\n                .replace(/\\)/g, '%29')\n                .replace(/\\*/g, '%2A');\n        }\n\n        /**\n         * Encodes param according to RF1738 standard.\n         *\n         * @param {string} str\n         * @returns {string}\n         */\n        function encodeComponent(str)\n        {\n            return encodeComponentRaw(str).replace(/%20/g, '+');\n        }\n\n        /**\n         * Encode single GET param.\n         *\n         * @param {string} key\n         * @param {string} val\n         * @param {string} argSeparator\n         * @param {function (string)} encodeFunc\n         * @returns {string}\n         */\n        function buildParam(key, val, argSeparator, encodeFunc)\n        {\n            var result = [];\n            if (val === true) {\n                val = '1';\n            } else if (val === false) {\n                val = '0';\n            }\n\n            if (val !== null) {\n                if (typeof val === 'object') {\n                    for (var index in val) {\n                        if (val[index] !== null) {\n                            result.push(buildParam(key + '[' + index + ']', val[index], argSeparator, encodeFunc));\n                        }\n                    }\n\n                    return result.join(argSeparator);\n                } else if (typeof val !== 'function') {\n                    return encodeFunc(key) + '=' + encodeFunc(val);\n                } else {\n                    throw new Error('There was an error processing for http_build_query().');\n                }\n            } else {\n                return '';\n            }\n        };\n\n        /**\n         * Builds HTTP query in the same way as PHP htp_build_query() function.\n         *\n         * @param {array} formData\n         * @param {string} numericPrefix\n         * @param {string} argSeparator\n         * @param {string} encType\n         * @returns {string}\n         */\n        function httpBuildQuery(formData, numericPrefix, argSeparator, encType)\n        {\n            var result = [],\n                encode = (encType == 'PHP_QUERY_RFC3986') ? encodeComponentRaw : encodeComponent;\n            if (!argSeparator) {\n                argSeparator = '&';\n            }\n\n            for (var key in formData) {\n                if (numericPrefix && !isNaN(key)) {\n                    key = String(numericPrefix) + key;\n                }\n                var query = buildParam(key, formData[key], argSeparator, encode);\n                if (query !== '') {\n                    result.push(query);\n                }\n            }\n\n            return result.join(argSeparator);\n        };\n\n        return function (formData, numericPrefix, argSeparator, encType) {\n            return httpBuildQuery(formData, numericPrefix, argSeparator, encType);\n        }\n    }\n);\n","Amasty_Base/vendor/slick/slick.min.js":"/* phpcs:ignoreFile */\n/*\n     _ _      _       _\n ___| (_) ___| | __  (_)___\n/ __| | |/ __| |/ /  | / __|\n\\__ \\ | | (__|   < _ | \\__ \\\n|___/_|_|\\___|_|\\_(_)/ |___/\n                   |__/\n Version: 1.9.0\n  Author: Ken Wheeler\n Website: http://kenwheeler.github.io\n    Docs: http://kenwheeler.github.io/slick\n    Repo: http://github.com/kenwheeler/slick\n  Issues: http://github.com/kenwheeler/slick/issues\n */\n(function(i){\"use strict\";\"function\"==typeof define&&define.amd?define([\"jquery\"],i):\"undefined\"!=typeof exports?module.exports=i(require(\"jquery\")):i(jQuery)})(function(i){\"use strict\";var e=window.Slick||{};e=function(){function e(e,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(e),appendDots:i(e),arrows:!0,asNavFor:null,prevArrow:'<button class=\"slick-prev\" aria-label=\"Previous\" type=\"button\">Previous</button>',nextArrow:'<button class=\"slick-next\" aria-label=\"Next\" type=\"button\">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:\"50px\",cssEase:\"ease\",customPaging:function(e,t){return i('<button type=\"button\" />').text(t+1)},dots:!1,dotsClass:\"slick-dots\",draggable:!0,easing:\"linear\",edgeFriction:.35,fade:!1,focusOnSelect:!1,focusOnChange:!1,infinite:!0,initialSlide:0,lazyLoad:\"ondemand\",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:\"window\",responsive:null,rows:1,rtl:!1,slide:\"\",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},n.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,scrolling:!1,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,swiping:!1,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},i.extend(n,n.initials),n.activeBreakpoint=null,n.animType=null,n.animProp=null,n.breakpoints=[],n.breakpointSettings=[],n.cssTransitions=!1,n.focussed=!1,n.interrupted=!1,n.hidden=\"hidden\",n.paused=!0,n.positionProp=null,n.respondTo=null,n.rowCount=1,n.shouldClick=!0,n.$slider=i(e),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange=\"visibilitychange\",n.windowWidth=0,n.windowTimer=null,s=i(e).data(\"slick\")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,\"undefined\"!=typeof document.mozHidden?(n.hidden=\"mozHidden\",n.visibilityChange=\"mozvisibilitychange\"):\"undefined\"!=typeof document.webkitHidden&&(n.hidden=\"webkitHidden\",n.visibilityChange=\"webkitvisibilitychange\"),n.autoPlay=i.proxy(n.autoPlay,n),n.autoPlayClear=i.proxy(n.autoPlayClear,n),n.autoPlayIterator=i.proxy(n.autoPlayIterator,n),n.changeSlide=i.proxy(n.changeSlide,n),n.clickHandler=i.proxy(n.clickHandler,n),n.selectHandler=i.proxy(n.selectHandler,n),n.setPosition=i.proxy(n.setPosition,n),n.swipeHandler=i.proxy(n.swipeHandler,n),n.dragHandler=i.proxy(n.dragHandler,n),n.keyHandler=i.proxy(n.keyHandler,n),n.instanceUid=t++,n.htmlExpr=/^(?:\\s*(<[\\w\\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}var t=0;return e}(),e.prototype.activateADA=function(){var i=this;i.$slideTrack.find(\".slick-active\").attr({\"aria-hidden\":\"false\"}).find(\"a, input, button, select\").attr({tabindex:\"0\"})},e.prototype.addSlide=e.prototype.slickAdd=function(e,t,o){var s=this;if(\"boolean\"==typeof t)o=t,t=null;else if(t<0||t>=s.slideCount)return!1;s.unload(),\"number\"==typeof t?0===t&&0===s.$slides.length?i(e).appendTo(s.$slideTrack):o?i(e).insertBefore(s.$slides.eq(t)):i(e).insertAfter(s.$slides.eq(t)):o===!0?i(e).prependTo(s.$slideTrack):i(e).appendTo(s.$slideTrack),s.$slides=s.$slideTrack.children(this.options.slide),s.$slideTrack.children(this.options.slide).detach(),s.$slideTrack.append(s.$slides),s.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e)}),s.$slidesCache=s.$slides,s.reinit()},e.prototype.animateHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.animate({height:e},i.options.speed)}},e.prototype.animateSlide=function(e,t){var o={},s=this;s.animateHeight(),s.options.rtl===!0&&s.options.vertical===!1&&(e=-e),s.transformsEnabled===!1?s.options.vertical===!1?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):s.cssTransitions===!1?(s.options.rtl===!0&&(s.currentLeft=-s.currentLeft),i({animStart:s.currentLeft}).animate({animStart:e},{duration:s.options.speed,easing:s.options.easing,step:function(i){i=Math.ceil(i),s.options.vertical===!1?(o[s.animType]=\"translate(\"+i+\"px, 0px)\",s.$slideTrack.css(o)):(o[s.animType]=\"translate(0px,\"+i+\"px)\",s.$slideTrack.css(o))},complete:function(){t&&t.call()}})):(s.applyTransition(),e=Math.ceil(e),s.options.vertical===!1?o[s.animType]=\"translate3d(\"+e+\"px, 0px, 0px)\":o[s.animType]=\"translate3d(0px,\"+e+\"px, 0px)\",s.$slideTrack.css(o),t&&setTimeout(function(){s.disableTransition(),t.call()},s.options.speed))},e.prototype.getNavTarget=function(){var e=this,t=e.options.asNavFor;return t&&null!==t&&(t=i(t).not(e.$slider)),t},e.prototype.asNavFor=function(e){var t=this,o=t.getNavTarget();null!==o&&\"object\"==typeof o&&o.each(function(){var t=i(this).slick(\"getSlick\");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};e.options.fade===!1?t[e.transitionType]=e.transformType+\" \"+e.options.speed+\"ms \"+e.options.cssEase:t[e.transitionType]=\"opacity \"+e.options.speed+\"ms \"+e.options.cssEase,e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.autoPlay=function(){var i=this;i.autoPlayClear(),i.slideCount>i.options.slidesToShow&&(i.autoPlayTimer=setInterval(i.autoPlayIterator,i.options.autoplaySpeed))},e.prototype.autoPlayClear=function(){var i=this;i.autoPlayTimer&&clearInterval(i.autoPlayTimer)},e.prototype.autoPlayIterator=function(){var i=this,e=i.currentSlide+i.options.slidesToScroll;i.paused||i.interrupted||i.focussed||(i.options.infinite===!1&&(1===i.direction&&i.currentSlide+1===i.slideCount-1?i.direction=0:0===i.direction&&(e=i.currentSlide-i.options.slidesToScroll,i.currentSlide-1===0&&(i.direction=1))),i.slideHandler(e))},e.prototype.buildArrows=function(){var e=this;e.options.arrows===!0&&(e.$prevArrow=i(e.options.prevArrow).addClass(\"slick-arrow\"),e.$nextArrow=i(e.options.nextArrow).addClass(\"slick-arrow\"),e.slideCount>e.options.slidesToShow?(e.$prevArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.$nextArrow.removeClass(\"slick-hidden\").removeAttr(\"aria-hidden tabindex\"),e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.prependTo(e.options.appendArrows),e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.appendTo(e.options.appendArrows),e.options.infinite!==!0&&e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\")):e.$prevArrow.add(e.$nextArrow).addClass(\"slick-hidden\").attr({\"aria-disabled\":\"true\",tabindex:\"-1\"}))},e.prototype.buildDots=function(){var e,t,o=this;if(o.options.dots===!0&&o.slideCount>o.options.slidesToShow){for(o.$slider.addClass(\"slick-dotted\"),t=i(\"<ul />\").addClass(o.options.dotsClass),e=0;e<=o.getDotCount();e+=1)t.append(i(\"<li />\").append(o.options.customPaging.call(this,o,e)));o.$dots=t.appendTo(o.options.appendDots),o.$dots.find(\"li\").first().addClass(\"slick-active\")}},e.prototype.buildOut=function(){var e=this;e.$slides=e.$slider.children(e.options.slide+\":not(.slick-cloned)\").addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.$slides.each(function(e,t){i(t).attr(\"data-slick-index\",e).data(\"originalStyling\",i(t).attr(\"style\")||\"\")}),e.$slider.addClass(\"slick-slider\"),e.$slideTrack=0===e.slideCount?i('<div class=\"slick-track\"/>').appendTo(e.$slider):e.$slides.wrapAll('<div class=\"slick-track\"/>').parent(),e.$list=e.$slideTrack.wrap('<div class=\"slick-list\"/>').parent(),e.$slideTrack.css(\"opacity\",0),e.options.centerMode!==!0&&e.options.swipeToSlide!==!0||(e.options.slidesToScroll=1),i(\"img[data-lazy]\",e.$slider).not(\"[src]\").addClass(\"slick-loading\"),e.setupInfinite(),e.buildArrows(),e.buildDots(),e.updateDots(),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.options.draggable===!0&&e.$list.addClass(\"draggable\")},e.prototype.buildRows=function(){var i,e,t,o,s,n,r,l=this;if(o=document.createDocumentFragment(),n=l.$slider.children(),l.options.rows>0){for(r=l.options.slidesPerRow*l.options.rows,s=Math.ceil(n.length/r),i=0;i<s;i++){var d=document.createElement(\"div\");for(e=0;e<l.options.rows;e++){var a=document.createElement(\"div\");for(t=0;t<l.options.slidesPerRow;t++){var c=i*r+(e*l.options.slidesPerRow+t);n.get(c)&&a.appendChild(n.get(c))}d.appendChild(a)}o.appendChild(d)}l.$slider.empty().append(o),l.$slider.children().children().children().css({width:100/l.options.slidesPerRow+\"%\",display:\"inline-block\"})}},e.prototype.checkResponsive=function(e,t){var o,s,n,r=this,l=!1,d=r.$slider.width(),a=window.innerWidth||i(window).width();if(\"window\"===r.respondTo?n=a:\"slider\"===r.respondTo?n=d:\"min\"===r.respondTo&&(n=Math.min(a,d)),r.options.responsive&&r.options.responsive.length&&null!==r.options.responsive){s=null;for(o in r.breakpoints)r.breakpoints.hasOwnProperty(o)&&(r.originalSettings.mobileFirst===!1?n<r.breakpoints[o]&&(s=r.breakpoints[o]):n>r.breakpoints[o]&&(s=r.breakpoints[o]));null!==s?null!==r.activeBreakpoint?(s!==r.activeBreakpoint||t)&&(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):(r.activeBreakpoint=s,\"unslick\"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,e===!0&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||l===!1||r.$slider.trigger(\"breakpoint\",[r,l])}},e.prototype.changeSlide=function(e,t){var o,s,n,r=this,l=i(e.currentTarget);switch(l.is(\"a\")&&e.preventDefault(),l.is(\"li\")||(l=l.closest(\"li\")),n=r.slideCount%r.options.slidesToScroll!==0,o=n?0:(r.slideCount-r.currentSlide)%r.options.slidesToScroll,e.data.message){case\"previous\":s=0===o?r.options.slidesToScroll:r.options.slidesToShow-o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide-s,!1,t);break;case\"next\":s=0===o?r.options.slidesToScroll:o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide+s,!1,t);break;case\"index\":var d=0===e.data.index?0:e.data.index||l.index()*r.options.slidesToScroll;r.slideHandler(r.checkNavigable(d),!1,t),l.children().trigger(\"focus\");break;default:return}},e.prototype.checkNavigable=function(i){var e,t,o=this;if(e=o.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var s in e){if(i<e[s]){i=t;break}t=e[s]}return i},e.prototype.cleanUpEvents=function(){var e=this;e.options.dots&&null!==e.$dots&&(i(\"li\",e.$dots).off(\"click.slick\",e.changeSlide).off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)),e.options.accessibility===!0&&e.$dots.off(\"keydown.slick\",e.keyHandler)),e.$slider.off(\"focus.slick blur.slick\"),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off(\"click.slick\",e.changeSlide),e.$nextArrow&&e.$nextArrow.off(\"click.slick\",e.changeSlide),e.options.accessibility===!0&&(e.$prevArrow&&e.$prevArrow.off(\"keydown.slick\",e.keyHandler),e.$nextArrow&&e.$nextArrow.off(\"keydown.slick\",e.keyHandler))),e.$list.off(\"touchstart.slick mousedown.slick\",e.swipeHandler),e.$list.off(\"touchmove.slick mousemove.slick\",e.swipeHandler),e.$list.off(\"touchend.slick mouseup.slick\",e.swipeHandler),e.$list.off(\"touchcancel.slick mouseleave.slick\",e.swipeHandler),e.$list.off(\"click.slick\",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),e.options.accessibility===!0&&e.$list.off(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().off(\"click.slick\",e.selectHandler),i(window).off(\"orientationchange.slick.slick-\"+e.instanceUid,e.orientationChange),i(window).off(\"resize.slick.slick-\"+e.instanceUid,e.resize),i(\"[draggable!=true]\",e.$slideTrack).off(\"dragstart\",e.preventDefault),i(window).off(\"load.slick.slick-\"+e.instanceUid,e.setPosition)},e.prototype.cleanUpSlideEvents=function(){var e=this;e.$list.off(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.off(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.cleanUpRows=function(){var i,e=this;e.options.rows>0&&(i=e.$slides.children().children(),i.removeAttr(\"style\"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){var e=this;e.shouldClick===!1&&(i.stopImmediatePropagation(),i.stopPropagation(),i.preventDefault())},e.prototype.destroy=function(e){var t=this;t.autoPlayClear(),t.touchObject={},t.cleanUpEvents(),i(\".slick-cloned\",t.$slider).detach(),t.$dots&&t.$dots.remove(),t.$prevArrow&&t.$prevArrow.length&&(t.$prevArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.prevArrow)&&t.$prevArrow.remove()),t.$nextArrow&&t.$nextArrow.length&&(t.$nextArrow.removeClass(\"slick-disabled slick-arrow slick-hidden\").removeAttr(\"aria-hidden aria-disabled tabindex\").css(\"display\",\"\"),t.htmlExpr.test(t.options.nextArrow)&&t.$nextArrow.remove()),t.$slides&&(t.$slides.removeClass(\"slick-slide slick-active slick-center slick-visible slick-current\").removeAttr(\"aria-hidden\").removeAttr(\"data-slick-index\").each(function(){i(this).attr(\"style\",i(this).data(\"originalStyling\"))}),t.$slideTrack.children(this.options.slide).detach(),t.$slideTrack.detach(),t.$list.detach(),t.$slider.append(t.$slides)),t.cleanUpRows(),t.$slider.removeClass(\"slick-slider\"),t.$slider.removeClass(\"slick-initialized\"),t.$slider.removeClass(\"slick-dotted\"),t.unslicked=!0,e||t.$slider.trigger(\"destroy\",[t])},e.prototype.disableTransition=function(i){var e=this,t={};t[e.transitionType]=\"\",e.options.fade===!1?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;t.cssTransitions===!1?(t.$slides.eq(i).css({zIndex:t.options.zIndex}),t.$slides.eq(i).animate({opacity:1},t.options.speed,t.options.easing,e)):(t.applyTransition(i),t.$slides.eq(i).css({opacity:1,zIndex:t.options.zIndex}),e&&setTimeout(function(){t.disableTransition(i),e.call()},t.options.speed))},e.prototype.fadeSlideOut=function(i){var e=this;e.cssTransitions===!1?e.$slides.eq(i).animate({opacity:0,zIndex:e.options.zIndex-2},e.options.speed,e.options.easing):(e.applyTransition(i),e.$slides.eq(i).css({opacity:0,zIndex:e.options.zIndex-2}))},e.prototype.filterSlides=e.prototype.slickFilter=function(i){var e=this;null!==i&&(e.$slidesCache=e.$slides,e.unload(),e.$slideTrack.children(this.options.slide).detach(),e.$slidesCache.filter(i).appendTo(e.$slideTrack),e.reinit())},e.prototype.focusHandler=function(){var e=this;e.$slider.off(\"focus.slick blur.slick\").on(\"focus.slick\",\"*\",function(t){var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&o.is(\":focus\")&&(e.focussed=!0,e.autoPlay())},0)}).on(\"blur.slick\",\"*\",function(t){i(this);e.options.pauseOnFocus&&(e.focussed=!1,e.autoPlay())})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){var i=this;return i.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(i.options.infinite===!0)if(i.slideCount<=i.options.slidesToShow)++o;else for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else if(i.options.centerMode===!0)o=i.slideCount;else if(i.options.asNavFor)for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else o=1+Math.ceil((i.slideCount-i.options.slidesToShow)/i.options.slidesToScroll);return o-1},e.prototype.getLeft=function(i){var e,t,o,s,n=this,r=0;return n.slideOffset=0,t=n.$slides.first().outerHeight(!0),n.options.infinite===!0?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,n.options.vertical===!0&&n.options.centerMode===!0&&(2===n.options.slidesToShow?s=-1.5:1===n.options.slidesToShow&&(s=-2)),r=t*n.options.slidesToShow*s),n.slideCount%n.options.slidesToScroll!==0&&i+n.options.slidesToScroll>n.slideCount&&n.slideCount>n.options.slidesToShow&&(i>n.slideCount?(n.slideOffset=(n.options.slidesToShow-(i-n.slideCount))*n.slideWidth*-1,r=(n.options.slidesToShow-(i-n.slideCount))*t*-1):(n.slideOffset=n.slideCount%n.options.slidesToScroll*n.slideWidth*-1,r=n.slideCount%n.options.slidesToScroll*t*-1))):i+n.options.slidesToShow>n.slideCount&&(n.slideOffset=(i+n.options.slidesToShow-n.slideCount)*n.slideWidth,r=(i+n.options.slidesToShow-n.slideCount)*t),n.slideCount<=n.options.slidesToShow&&(n.slideOffset=0,r=0),n.options.centerMode===!0&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:n.options.centerMode===!0&&n.options.infinite===!0?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:n.options.centerMode===!0&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=n.options.vertical===!1?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,n.options.variableWidth===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,n.options.centerMode===!0&&(o=n.slideCount<=n.options.slidesToShow||n.options.infinite===!1?n.$slideTrack.children(\".slick-slide\").eq(i):n.$slideTrack.children(\".slick-slide\").eq(i+n.options.slidesToShow+1),e=n.options.rtl===!0?o[0]?(n.$slideTrack.width()-o[0].offsetLeft-o.width())*-1:0:o[0]?o[0].offsetLeft*-1:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){var e=this;return e.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(e.options.infinite===!1?i=e.slideCount:(t=e.options.slidesToScroll*-1,o=e.options.slidesToScroll*-1,i=2*e.slideCount);t<i;)s.push(t),t=o+e.options.slidesToScroll,o+=e.options.slidesToScroll<=e.options.slidesToShow?e.options.slidesToScroll:e.options.slidesToShow;return s},e.prototype.getSlick=function(){return this},e.prototype.getSlideCount=function(){var e,t,o,s,n=this;return s=n.options.centerMode===!0?Math.floor(n.$list.width()/2):0,o=n.swipeLeft*-1+s,n.options.swipeToSlide===!0?(n.$slideTrack.find(\".slick-slide\").each(function(e,s){var r,l,d;if(r=i(s).outerWidth(),l=s.offsetLeft,n.options.centerMode!==!0&&(l+=r/2),d=l+r,o<d)return t=s,!1}),e=Math.abs(i(t).attr(\"data-slick-index\")-n.currentSlide)||1):n.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){var t=this;t.changeSlide({data:{message:\"index\",index:parseInt(i)}},e)},e.prototype.init=function(e){var t=this;i(t.$slider).hasClass(\"slick-initialized\")||(i(t.$slider).addClass(\"slick-initialized\"),t.buildRows(),t.buildOut(),t.setProps(),t.startLoad(),t.loadSlider(),t.initializeEvents(),t.updateArrows(),t.updateDots(),t.checkResponsive(!0),t.focusHandler()),e&&t.$slider.trigger(\"init\",[t]),t.options.accessibility===!0&&t.initADA(),t.options.autoplay&&(t.paused=!1,t.autoPlay())},e.prototype.initADA=function(){var e=this,t=Math.ceil(e.slideCount/e.options.slidesToShow),o=e.getNavigableIndexes().filter(function(i){return i>=0&&i<e.slideCount});e.$slides.add(e.$slideTrack.find(\".slick-cloned\")).attr({\"aria-hidden\":\"true\",tabindex:\"-1\"}).find(\"a, input, button, select\").attr({tabindex:\"-1\"}),null!==e.$dots&&(e.$slides.not(e.$slideTrack.find(\".slick-cloned\")).each(function(t){var s=o.indexOf(t);if(i(this).attr({role:\"tabpanel\",id:\"slick-slide\"+e.instanceUid+t,tabindex:-1}),s!==-1){var n=\"slick-slide-control\"+e.instanceUid+s;i(\"#\"+n).length&&i(this).attr({\"aria-describedby\":n})}}),e.$dots.attr(\"role\",\"tablist\").find(\"li\").each(function(s){var n=o[s];i(this).attr({role:\"presentation\"}),i(this).find(\"button\").first().attr({role:\"tab\",id:\"slick-slide-control\"+e.instanceUid+s,\"aria-controls\":\"slick-slide\"+e.instanceUid+n,\"aria-label\":s+1+\" of \"+t,\"aria-selected\":null,tabindex:\"-1\"})}).eq(e.currentSlide).find(\"button\").attr({\"aria-selected\":\"true\",tabindex:\"0\"}).end());for(var s=e.currentSlide,n=s+e.options.slidesToShow;s<n;s++)e.options.focusOnChange?e.$slides.eq(s).attr({tabindex:\"0\"}):e.$slides.eq(s).removeAttr(\"tabindex\");e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.off(\"click.slick\").on(\"click.slick\",{message:\"previous\"},i.changeSlide),i.$nextArrow.off(\"click.slick\").on(\"click.slick\",{message:\"next\"},i.changeSlide),i.options.accessibility===!0&&(i.$prevArrow.on(\"keydown.slick\",i.keyHandler),i.$nextArrow.on(\"keydown.slick\",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;e.options.dots===!0&&e.slideCount>e.options.slidesToShow&&(i(\"li\",e.$dots).on(\"click.slick\",{message:\"index\"},e.changeSlide),e.options.accessibility===!0&&e.$dots.on(\"keydown.slick\",e.keyHandler)),e.options.dots===!0&&e.options.pauseOnDotsHover===!0&&e.slideCount>e.options.slidesToShow&&i(\"li\",e.$dots).on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)).on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1))},e.prototype.initSlideEvents=function(){var e=this;e.options.pauseOnHover&&(e.$list.on(\"mouseenter.slick\",i.proxy(e.interrupt,e,!0)),e.$list.on(\"mouseleave.slick\",i.proxy(e.interrupt,e,!1)))},e.prototype.initializeEvents=function(){var e=this;e.initArrowEvents(),e.initDotEvents(),e.initSlideEvents(),e.$list.on(\"touchstart.slick mousedown.slick\",{action:\"start\"},e.swipeHandler),e.$list.on(\"touchmove.slick mousemove.slick\",{action:\"move\"},e.swipeHandler),e.$list.on(\"touchend.slick mouseup.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"touchcancel.slick mouseleave.slick\",{action:\"end\"},e.swipeHandler),e.$list.on(\"click.slick\",e.clickHandler),i(document).on(e.visibilityChange,i.proxy(e.visibility,e)),e.options.accessibility===!0&&e.$list.on(\"keydown.slick\",e.keyHandler),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),i(window).on(\"orientationchange.slick.slick-\"+e.instanceUid,i.proxy(e.orientationChange,e)),i(window).on(\"resize.slick.slick-\"+e.instanceUid,i.proxy(e.resize,e)),i(\"[draggable!=true]\",e.$slideTrack).on(\"dragstart\",e.preventDefault),i(window).on(\"load.slick.slick-\"+e.instanceUid,e.setPosition),i(e.setPosition)},e.prototype.initUI=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.show()},e.prototype.keyHandler=function(i){var e=this;i.target.tagName.match(\"TEXTAREA|INPUT|SELECT\")||(37===i.keyCode&&e.options.accessibility===!0?e.changeSlide({data:{message:e.options.rtl===!0?\"next\":\"previous\"}}):39===i.keyCode&&e.options.accessibility===!0&&e.changeSlide({data:{message:e.options.rtl===!0?\"previous\":\"next\"}}))},e.prototype.lazyLoad=function(){function e(e){i(\"img[data-lazy]\",e).each(function(){var e=i(this),t=i(this).attr(\"data-lazy\"),o=i(this).attr(\"data-srcset\"),s=i(this).attr(\"data-sizes\")||r.$slider.attr(\"data-sizes\"),n=document.createElement(\"img\");n.onload=function(){e.animate({opacity:0},100,function(){o&&(e.attr(\"srcset\",o),s&&e.attr(\"sizes\",s)),e.attr(\"src\",t).animate({opacity:1},200,function(){e.removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\")}),r.$slider.trigger(\"lazyLoaded\",[r,e,t])})},n.onerror=function(){e.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),r.$slider.trigger(\"lazyLoadError\",[r,e,t])},n.src=t})}var t,o,s,n,r=this;if(r.options.centerMode===!0?r.options.infinite===!0?(s=r.currentSlide+(r.options.slidesToShow/2+1),n=s+r.options.slidesToShow+2):(s=Math.max(0,r.currentSlide-(r.options.slidesToShow/2+1)),n=2+(r.options.slidesToShow/2+1)+r.currentSlide):(s=r.options.infinite?r.options.slidesToShow+r.currentSlide:r.currentSlide,n=Math.ceil(s+r.options.slidesToShow),r.options.fade===!0&&(s>0&&s--,n<=r.slideCount&&n++)),t=r.$slider.find(\".slick-slide\").slice(s,n),\"anticipated\"===r.options.lazyLoad)for(var l=s-1,d=n,a=r.$slider.find(\".slick-slide\"),c=0;c<r.options.slidesToScroll;c++)l<0&&(l=r.slideCount-1),t=t.add(a.eq(l)),t=t.add(a.eq(d)),l--,d++;e(t),r.slideCount<=r.options.slidesToShow?(o=r.$slider.find(\".slick-slide\"),e(o)):r.currentSlide>=r.slideCount-r.options.slidesToShow?(o=r.$slider.find(\".slick-cloned\").slice(0,r.options.slidesToShow),e(o)):0===r.currentSlide&&(o=r.$slider.find(\".slick-cloned\").slice(r.options.slidesToShow*-1),e(o))},e.prototype.loadSlider=function(){var i=this;i.setPosition(),i.$slideTrack.css({opacity:1}),i.$slider.removeClass(\"slick-loading\"),i.initUI(),\"progressive\"===i.options.lazyLoad&&i.progressiveLazyLoad()},e.prototype.next=e.prototype.slickNext=function(){var i=this;i.changeSlide({data:{message:\"next\"}})},e.prototype.orientationChange=function(){var i=this;i.checkResponsive(),i.setPosition()},e.prototype.pause=e.prototype.slickPause=function(){var i=this;i.autoPlayClear(),i.paused=!0},e.prototype.play=e.prototype.slickPlay=function(){var i=this;i.autoPlay(),i.options.autoplay=!0,i.paused=!1,i.focussed=!1,i.interrupted=!1},e.prototype.postSlide=function(e){var t=this;if(!t.unslicked&&(t.$slider.trigger(\"afterChange\",[t,e]),t.animating=!1,t.slideCount>t.options.slidesToShow&&t.setPosition(),t.swipeLeft=null,t.options.autoplay&&t.autoPlay(),t.options.accessibility===!0&&(t.initADA(),t.options.focusOnChange))){var o=i(t.$slides.get(t.currentSlide));o.attr(\"tabindex\",0).focus()}},e.prototype.prev=e.prototype.slickPrev=function(){var i=this;i.changeSlide({data:{message:\"previous\"}})},e.prototype.preventDefault=function(i){i.preventDefault()},e.prototype.progressiveLazyLoad=function(e){e=e||1;var t,o,s,n,r,l=this,d=i(\"img[data-lazy]\",l.$slider);d.length?(t=d.first(),o=t.attr(\"data-lazy\"),s=t.attr(\"data-srcset\"),n=t.attr(\"data-sizes\")||l.$slider.attr(\"data-sizes\"),r=document.createElement(\"img\"),r.onload=function(){s&&(t.attr(\"srcset\",s),n&&t.attr(\"sizes\",n)),t.attr(\"src\",o).removeAttr(\"data-lazy data-srcset data-sizes\").removeClass(\"slick-loading\"),l.options.adaptiveHeight===!0&&l.setPosition(),l.$slider.trigger(\"lazyLoaded\",[l,t,o]),l.progressiveLazyLoad()},r.onerror=function(){e<3?setTimeout(function(){l.progressiveLazyLoad(e+1)},500):(t.removeAttr(\"data-lazy\").removeClass(\"slick-loading\").addClass(\"slick-lazyload-error\"),l.$slider.trigger(\"lazyLoadError\",[l,t,o]),l.progressiveLazyLoad())},r.src=o):l.$slider.trigger(\"allImagesLoaded\",[l])},e.prototype.refresh=function(e){var t,o,s=this;o=s.slideCount-s.options.slidesToShow,!s.options.infinite&&s.currentSlide>o&&(s.currentSlide=o),s.slideCount<=s.options.slidesToShow&&(s.currentSlide=0),t=s.currentSlide,s.destroy(!0),i.extend(s,s.initials,{currentSlide:t}),s.init(),e||s.changeSlide({data:{message:\"index\",index:t}},!1)},e.prototype.registerBreakpoints=function(){var e,t,o,s=this,n=s.options.responsive||null;if(\"array\"===i.type(n)&&n.length){s.respondTo=s.options.respondTo||\"window\";for(e in n)if(o=s.breakpoints.length-1,n.hasOwnProperty(e)){for(t=n[e].breakpoint;o>=0;)s.breakpoints[o]&&s.breakpoints[o]===t&&s.breakpoints.splice(o,1),o--;s.breakpoints.push(t),s.breakpointSettings[t]=n[e].settings}s.breakpoints.sort(function(i,e){return s.options.mobileFirst?i-e:e-i})}},e.prototype.reinit=function(){var e=this;e.$slides=e.$slideTrack.children(e.options.slide).addClass(\"slick-slide\"),e.slideCount=e.$slides.length,e.currentSlide>=e.slideCount&&0!==e.currentSlide&&(e.currentSlide=e.currentSlide-e.options.slidesToScroll),e.slideCount<=e.options.slidesToShow&&(e.currentSlide=0),e.registerBreakpoints(),e.setProps(),e.setupInfinite(),e.buildArrows(),e.updateArrows(),e.initArrowEvents(),e.buildDots(),e.updateDots(),e.initDotEvents(),e.cleanUpSlideEvents(),e.initSlideEvents(),e.checkResponsive(!1,!0),e.options.focusOnSelect===!0&&i(e.$slideTrack).children().on(\"click.slick\",e.selectHandler),e.setSlideClasses(\"number\"==typeof e.currentSlide?e.currentSlide:0),e.setPosition(),e.focusHandler(),e.paused=!e.options.autoplay,e.autoPlay(),e.$slider.trigger(\"reInit\",[e])},e.prototype.resize=function(){var e=this;i(window).width()!==e.windowWidth&&(clearTimeout(e.windowDelay),e.windowDelay=window.setTimeout(function(){e.windowWidth=i(window).width(),e.checkResponsive(),e.unslicked||e.setPosition()},50))},e.prototype.removeSlide=e.prototype.slickRemove=function(i,e,t){var o=this;return\"boolean\"==typeof i?(e=i,i=e===!0?0:o.slideCount-1):i=e===!0?--i:i,!(o.slideCount<1||i<0||i>o.slideCount-1)&&(o.unload(),t===!0?o.$slideTrack.children().remove():o.$slideTrack.children(this.options.slide).eq(i).remove(),o.$slides=o.$slideTrack.children(this.options.slide),o.$slideTrack.children(this.options.slide).detach(),o.$slideTrack.append(o.$slides),o.$slidesCache=o.$slides,void o.reinit())},e.prototype.setCSS=function(i){var e,t,o=this,s={};o.options.rtl===!0&&(i=-i),e=\"left\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",t=\"top\"==o.positionProp?Math.ceil(i)+\"px\":\"0px\",s[o.positionProp]=i,o.transformsEnabled===!1?o.$slideTrack.css(s):(s={},o.cssTransitions===!1?(s[o.animType]=\"translate(\"+e+\", \"+t+\")\",o.$slideTrack.css(s)):(s[o.animType]=\"translate3d(\"+e+\", \"+t+\", 0px)\",o.$slideTrack.css(s)))},e.prototype.setDimensions=function(){var i=this;i.options.vertical===!1?i.options.centerMode===!0&&i.$list.css({padding:\"0px \"+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),i.options.centerMode===!0&&i.$list.css({padding:i.options.centerPadding+\" 0px\"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),i.options.vertical===!1&&i.options.variableWidth===!1?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(\".slick-slide\").length))):i.options.variableWidth===!0?i.$slideTrack.width(5e3*i.slideCount):(i.slideWidth=Math.ceil(i.listWidth),i.$slideTrack.height(Math.ceil(i.$slides.first().outerHeight(!0)*i.$slideTrack.children(\".slick-slide\").length)));var e=i.$slides.first().outerWidth(!0)-i.$slides.first().width();i.options.variableWidth===!1&&i.$slideTrack.children(\".slick-slide\").width(i.slideWidth-e)},e.prototype.setFade=function(){var e,t=this;t.$slides.each(function(o,s){e=t.slideWidth*o*-1,t.options.rtl===!0?i(s).css({position:\"relative\",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}):i(s).css({position:\"relative\",left:e,top:0,zIndex:t.options.zIndex-2,opacity:0})}),t.$slides.eq(t.currentSlide).css({zIndex:t.options.zIndex-1,opacity:1})},e.prototype.setHeight=function(){var i=this;if(1===i.options.slidesToShow&&i.options.adaptiveHeight===!0&&i.options.vertical===!1){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.css(\"height\",e)}},e.prototype.setOption=e.prototype.slickSetOption=function(){var e,t,o,s,n,r=this,l=!1;if(\"object\"===i.type(arguments[0])?(o=arguments[0],l=arguments[1],n=\"multiple\"):\"string\"===i.type(arguments[0])&&(o=arguments[0],s=arguments[1],l=arguments[2],\"responsive\"===arguments[0]&&\"array\"===i.type(arguments[1])?n=\"responsive\":\"undefined\"!=typeof arguments[1]&&(n=\"single\")),\"single\"===n)r.options[o]=s;else if(\"multiple\"===n)i.each(o,function(i,e){r.options[i]=e});else if(\"responsive\"===n)for(t in s)if(\"array\"!==i.type(r.options.responsive))r.options.responsive=[s[t]];else{for(e=r.options.responsive.length-1;e>=0;)r.options.responsive[e].breakpoint===s[t].breakpoint&&r.options.responsive.splice(e,1),e--;r.options.responsive.push(s[t])}l&&(r.unload(),r.reinit())},e.prototype.setPosition=function(){var i=this;i.setDimensions(),i.setHeight(),i.options.fade===!1?i.setCSS(i.getLeft(i.currentSlide)):i.setFade(),i.$slider.trigger(\"setPosition\",[i])},e.prototype.setProps=function(){var i=this,e=document.body.style;i.positionProp=i.options.vertical===!0?\"top\":\"left\",\n    \"top\"===i.positionProp?i.$slider.addClass(\"slick-vertical\"):i.$slider.removeClass(\"slick-vertical\"),void 0===e.WebkitTransition&&void 0===e.MozTransition&&void 0===e.msTransition||i.options.useCSS===!0&&(i.cssTransitions=!0),i.options.fade&&(\"number\"==typeof i.options.zIndex?i.options.zIndex<3&&(i.options.zIndex=3):i.options.zIndex=i.defaults.zIndex),void 0!==e.OTransform&&(i.animType=\"OTransform\",i.transformType=\"-o-transform\",i.transitionType=\"OTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.MozTransform&&(i.animType=\"MozTransform\",i.transformType=\"-moz-transform\",i.transitionType=\"MozTransition\",void 0===e.perspectiveProperty&&void 0===e.MozPerspective&&(i.animType=!1)),void 0!==e.webkitTransform&&(i.animType=\"webkitTransform\",i.transformType=\"-webkit-transform\",i.transitionType=\"webkitTransition\",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.msTransform&&(i.animType=\"msTransform\",i.transformType=\"-ms-transform\",i.transitionType=\"msTransition\",void 0===e.msTransform&&(i.animType=!1)),void 0!==e.transform&&i.animType!==!1&&(i.animType=\"transform\",i.transformType=\"transform\",i.transitionType=\"transition\"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&i.animType!==!1},e.prototype.setSlideClasses=function(i){var e,t,o,s,n=this;if(t=n.$slider.find(\".slick-slide\").removeClass(\"slick-active slick-center slick-current\").attr(\"aria-hidden\",\"true\"),n.$slides.eq(i).addClass(\"slick-current\"),n.options.centerMode===!0){var r=n.options.slidesToShow%2===0?1:0;e=Math.floor(n.options.slidesToShow/2),n.options.infinite===!0&&(i>=e&&i<=n.slideCount-1-e?n.$slides.slice(i-e+r,i+e+1).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(o=n.options.slidesToShow+i,t.slice(o-e+1+r,o+e+2).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\")),0===i?t.eq(t.length-1-n.options.slidesToShow).addClass(\"slick-center\"):i===n.slideCount-1&&t.eq(n.options.slidesToShow).addClass(\"slick-center\")),n.$slides.eq(i).addClass(\"slick-center\")}else i>=0&&i<=n.slideCount-n.options.slidesToShow?n.$slides.slice(i,i+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.length<=n.options.slidesToShow?t.addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):(s=n.slideCount%n.options.slidesToShow,o=n.options.infinite===!0?n.options.slidesToShow+i:i,n.options.slidesToShow==n.options.slidesToScroll&&n.slideCount-i<n.options.slidesToShow?t.slice(o-(n.options.slidesToShow-s),o+s).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"):t.slice(o,o+n.options.slidesToShow).addClass(\"slick-active\").attr(\"aria-hidden\",\"false\"));\"ondemand\"!==n.options.lazyLoad&&\"anticipated\"!==n.options.lazyLoad||n.lazyLoad()},e.prototype.setupInfinite=function(){var e,t,o,s=this;if(s.options.fade===!0&&(s.options.centerMode=!1),s.options.infinite===!0&&s.options.fade===!1&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=s.options.centerMode===!0?s.options.slidesToShow+1:s.options.slidesToShow,e=s.slideCount;e>s.slideCount-o;e-=1)t=e-1,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t-s.slideCount).prependTo(s.$slideTrack).addClass(\"slick-cloned\");for(e=0;e<o+s.slideCount;e+=1)t=e,i(s.$slides[t]).clone(!0).attr(\"id\",\"\").attr(\"data-slick-index\",t+s.slideCount).appendTo(s.$slideTrack).addClass(\"slick-cloned\");s.$slideTrack.find(\".slick-cloned\").find(\"[id]\").each(function(){i(this).attr(\"id\",\"\")})}},e.prototype.interrupt=function(i){var e=this;i||e.autoPlay(),e.interrupted=i},e.prototype.selectHandler=function(e){var t=this,o=i(e.target).is(\".slick-slide\")?i(e.target):i(e.target).parents(\".slick-slide\"),s=parseInt(o.attr(\"data-slick-index\"));return s||(s=0),t.slideCount<=t.options.slidesToShow?void t.slideHandler(s,!1,!0):void t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(a.animating===!0&&a.options.waitForAnimate===!0||a.options.fade===!0&&a.currentSlide===i))return e===!1&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,a.options.infinite===!1&&a.options.centerMode===!1&&(i<0||i>a.getDotCount()*a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):a.options.infinite===!1&&a.options.centerMode===!0&&(i<0||i>a.slideCount-a.options.slidesToScroll)?void(a.options.fade===!1&&(o=a.currentSlide,t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o))):(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!==0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+o:o>=a.slideCount?a.slideCount%a.options.slidesToScroll!==0?0:o-a.slideCount:o,a.animating=!0,a.$slider.trigger(\"beforeChange\",[a,a.currentSlide,s]),n=a.currentSlide,a.currentSlide=s,a.setSlideClasses(a.currentSlide),a.options.asNavFor&&(l=a.getNavTarget(),l=l.slick(\"getSlick\"),l.slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide)),a.updateDots(),a.updateArrows(),a.options.fade===!0?(t!==!0?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight()):void(t!==!0&&a.slideCount>a.options.slidesToShow?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)))},e.prototype.startLoad=function(){var i=this;i.options.arrows===!0&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),i.options.dots===!0&&i.slideCount>i.options.slidesToShow&&i.$dots.hide(),i.$slider.addClass(\"slick-loading\")},e.prototype.swipeDirection=function(){var i,e,t,o,s=this;return i=s.touchObject.startX-s.touchObject.curX,e=s.touchObject.startY-s.touchObject.curY,t=Math.atan2(e,i),o=Math.round(180*t/Math.PI),o<0&&(o=360-Math.abs(o)),o<=45&&o>=0?s.options.rtl===!1?\"left\":\"right\":o<=360&&o>=315?s.options.rtl===!1?\"left\":\"right\":o>=135&&o<=225?s.options.rtl===!1?\"right\":\"left\":s.options.verticalSwiping===!0?o>=35&&o<=135?\"down\":\"up\":\"vertical\"},e.prototype.swipeEnd=function(i){var e,t,o=this;if(o.dragging=!1,o.swiping=!1,o.scrolling)return o.scrolling=!1,!1;if(o.interrupted=!1,o.shouldClick=!(o.touchObject.swipeLength>10),void 0===o.touchObject.curX)return!1;if(o.touchObject.edgeHit===!0&&o.$slider.trigger(\"edge\",[o,o.swipeDirection()]),o.touchObject.swipeLength>=o.touchObject.minSwipe){switch(t=o.swipeDirection()){case\"left\":case\"down\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide+o.getSlideCount()):o.currentSlide+o.getSlideCount(),o.currentDirection=0;break;case\"right\":case\"up\":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide-o.getSlideCount()):o.currentSlide-o.getSlideCount(),o.currentDirection=1}\"vertical\"!=t&&(o.slideHandler(e),o.touchObject={},o.$slider.trigger(\"swipe\",[o,t]))}else o.touchObject.startX!==o.touchObject.curX&&(o.slideHandler(o.currentSlide),o.touchObject={})},e.prototype.swipeHandler=function(i){var e=this;if(!(e.options.swipe===!1||\"ontouchend\"in document&&e.options.swipe===!1||e.options.draggable===!1&&i.type.indexOf(\"mouse\")!==-1))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,e.options.verticalSwiping===!0&&(e.touchObject.minSwipe=e.listHeight/e.options.touchThreshold),i.data.action){case\"start\":e.swipeStart(i);break;case\"move\":e.swipeMove(i);break;case\"end\":e.swipeEnd(i)}},e.prototype.swipeMove=function(i){var e,t,o,s,n,r,l=this;return n=void 0!==i.originalEvent?i.originalEvent.touches:null,!(!l.dragging||l.scrolling||n&&1!==n.length)&&(e=l.getLeft(l.currentSlide),l.touchObject.curX=void 0!==n?n[0].pageX:i.clientX,l.touchObject.curY=void 0!==n?n[0].pageY:i.clientY,l.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(l.touchObject.curX-l.touchObject.startX,2))),r=Math.round(Math.sqrt(Math.pow(l.touchObject.curY-l.touchObject.startY,2))),!l.options.verticalSwiping&&!l.swiping&&r>4?(l.scrolling=!0,!1):(l.options.verticalSwiping===!0&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(l.options.rtl===!1?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),l.options.verticalSwiping===!0&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,l.options.infinite===!1&&(0===l.currentSlide&&\"right\"===t||l.currentSlide>=l.getDotCount()&&\"left\"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),l.options.vertical===!1?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,l.options.verticalSwiping===!0&&(l.swipeLeft=e+o*s),l.options.fade!==!0&&l.options.touchMove!==!1&&(l.animating===!0?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;return t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow?(t.touchObject={},!1):(void 0!==i.originalEvent&&void 0!==i.originalEvent.touches&&(e=i.originalEvent.touches[0]),t.touchObject.startX=t.touchObject.curX=void 0!==e?e.pageX:i.clientX,t.touchObject.startY=t.touchObject.curY=void 0!==e?e.pageY:i.clientY,void(t.dragging=!0))},e.prototype.unfilterSlides=e.prototype.slickUnfilter=function(){var i=this;null!==i.$slidesCache&&(i.unload(),i.$slideTrack.children(this.options.slide).detach(),i.$slidesCache.appendTo(i.$slideTrack),i.reinit())},e.prototype.unload=function(){var e=this;i(\".slick-cloned\",e.$slider).remove(),e.$dots&&e.$dots.remove(),e.$prevArrow&&e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.remove(),e.$nextArrow&&e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.remove(),e.$slides.removeClass(\"slick-slide slick-active slick-visible slick-current\").attr(\"aria-hidden\",\"true\").css(\"width\",\"\")},e.prototype.unslick=function(i){var e=this;e.$slider.trigger(\"unslick\",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i,e=this;i=Math.floor(e.options.slidesToShow/2),e.options.arrows===!0&&e.slideCount>e.options.slidesToShow&&!e.options.infinite&&(e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\"),0===e.currentSlide?(e.$prevArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$nextArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-e.options.slidesToShow&&e.options.centerMode===!1?(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")):e.currentSlide>=e.slideCount-1&&e.options.centerMode===!0&&(e.$nextArrow.addClass(\"slick-disabled\").attr(\"aria-disabled\",\"true\"),e.$prevArrow.removeClass(\"slick-disabled\").attr(\"aria-disabled\",\"false\")))},e.prototype.updateDots=function(){var i=this;null!==i.$dots&&(i.$dots.find(\"li\").removeClass(\"slick-active\").end(),i.$dots.find(\"li\").eq(Math.floor(i.currentSlide/i.options.slidesToScroll)).addClass(\"slick-active\"))},e.prototype.visibility=function(){var i=this;i.options.autoplay&&(document[i.hidden]?i.interrupted=!0:i.interrupted=!1)},i.fn.slick=function(){var i,t,o=this,s=arguments[0],n=Array.prototype.slice.call(arguments,1),r=o.length;for(i=0;i<r;i++)if(\"object\"==typeof s||\"undefined\"==typeof s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),\"undefined\"!=typeof t)return t;return o}});\n","Magento_Vault/js/view/payment/vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\n/* @api */\ndefine([\n    'underscore',\n    'uiComponent',\n    'Magento_Checkout/js/model/payment/renderer-list',\n    'uiLayout',\n    'uiRegistry'\n], function (_, Component, rendererList, layout, registry) {\n    'use strict';\n\n    var vaultGroupName = 'vaultGroup';\n\n    layout([{\n        name: vaultGroupName,\n        component: 'Magento_Checkout/js/model/payment/method-group',\n        alias: 'vault',\n        sortOrder: 10\n    }]);\n\n    registry.get(vaultGroupName, function (vaultGroup) {\n        _.each(window.checkoutConfig.payment.vault, function (config, index) {\n            rendererList.push(\n                {\n                    type: index,\n                    config: config.config,\n                    component: config.component,\n                    group: vaultGroup,\n\n                    /**\n                     * Custom payment method types comparator\n                     * @param {String} typeA\n                     * @param {String} typeB\n                     * @return {Boolean}\n                     */\n                    typeComparatorCallback: function (typeA, typeB) {\n                        // vault token items have the same name as vault payment without index\n                        return typeA.substring(0, typeA.lastIndexOf('_')) === typeB;\n                    }\n                }\n            );\n        });\n    });\n\n    /**\n     * Add view logic here if needed\n     */\n    return Component.extend({});\n});\n","Magento_Vault/js/view/payment/vault-enabler.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\n/* @api */\ndefine(\n    [\n        'uiElement'\n    ],\n    function (\n        Component\n    ) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                isActivePaymentTokenEnabler: true\n            },\n\n            /**\n             * @param {String} paymentCode\n             */\n            setPaymentCode: function (paymentCode) {\n                this.paymentCode = paymentCode;\n            },\n\n            /**\n             * @returns {Object}\n             */\n            initObservable: function () {\n                this._super()\n                    .observe([\n                        'isActivePaymentTokenEnabler'\n                    ]);\n\n                return this;\n            },\n\n            /**\n             * @param {Object} data\n             */\n            visitAdditionalData: function (data) {\n                if (!this.isVaultEnabled()) {\n                    return;\n                }\n\n                if (!('additional_data' in data)) {\n                    data['additional_data'] = {};\n                }\n\n                data['additional_data']['is_active_payment_token_enabler'] = this.isActivePaymentTokenEnabler();\n            },\n\n            /**\n             * @returns {Boolean}\n             */\n            isVaultEnabled: function () {\n                return typeof window.checkoutConfig.vault[this.paymentCode] !== 'undefined' &&\n                    window.checkoutConfig.vault[this.paymentCode]['is_enabled'] === true;\n            }\n        });\n    }\n);\n","Magento_Vault/js/view/payment/method-renderer/vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n\ndefine(\n    [\n        'Magento_Checkout/js/view/payment/default',\n        'Magento_Checkout/js/action/select-payment-method',\n        'Magento_Checkout/js/checkout-data'\n    ],\n    function (Component, selectPaymentMethod, checkoutData) {\n        'use strict';\n\n        return Component.extend({\n            defaults: {\n                template: 'Magento_Vault/payment/form'\n            },\n\n            /**\n             * @returns {exports.initObservable}\n             */\n            initObservable: function () {\n                this._super()\n                    .observe([]);\n\n                return this;\n            },\n\n            /**\n             * @returns\n             */\n            selectPaymentMethod: function () {\n                selectPaymentMethod(\n                    {\n                        method: this.getId()\n                    }\n                );\n                checkoutData.setSelectedPaymentMethod(this.getId());\n\n                return true;\n            },\n\n            /**\n             * @returns {String}\n             */\n            getTitle: function () {\n                return '';\n            },\n\n            /**\n             * @returns {String}\n             */\n            getToken: function () {\n                return '';\n            },\n\n            /**\n             * @returns {String}\n             */\n            getId: function () {\n                return this.index;\n            },\n\n            /**\n             * @returns {String}\n             */\n            getCode: function () {\n                return this.code;\n            },\n\n            /**\n             * Get last 4 digits of card\n             * @returns {String}\n             */\n            getMaskedCard: function () {\n                return '';\n            },\n\n            /**\n             * Get expiration date\n             * @returns {String}\n             */\n            getExpirationDate: function () {\n                return '';\n            },\n\n            /**\n             * Get card type\n             * @returns {String}\n             */\n            getCardType: function () {\n                return '';\n            },\n\n            /**\n             * @param {String} type\n             * @returns {Boolean}\n             */\n            getIcons: function (type) {\n                return window.checkoutConfig.payment.ccform.icons.hasOwnProperty(type) ?\n                    window.checkoutConfig.payment.ccform.icons[type]\n                    : false;\n            },\n\n            /**\n             * Return state of place order button.\n             *\n             * @return {Boolean}\n             */\n            isButtonActive: function () {\n                return this.isActive() && this.isPlaceOrderActionAllowed();\n            },\n\n            /**\n             * Check if payment is active.\n             *\n             * @return {Boolean}\n             */\n            isActive: function () {\n                return this.isChecked() === this.getId();\n            },\n\n            /**\n             * @returns {*}\n             */\n            getData: function () {\n                var data = {\n                    method: this.getCode()\n                };\n\n                data['additional_data'] = {};\n                data['additional_data']['public_hash'] = this.getToken();\n\n                return data;\n            }\n        });\n    }\n);\n","Magento_Vault/js/customer_account/deleteWidget.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'Magento_Ui/js/modal/modalToggle',\n    'mage/translate'\n], function ($, modalToggle) {\n    'use strict';\n\n    return function (config, deleteButton) {\n        config.buttons = [\n            {\n                text: $.mage.__('Cancel'),\n                class: 'action secondary cancel'\n            }, {\n                text: $.mage.__('Delete'),\n                class: 'action primary',\n\n                /**\n                 * Default action on button click\n                 */\n                click: function (event) { //eslint-disable-line no-unused-vars\n                    $(deleteButton.form).trigger('submit');\n                }\n            }\n        ];\n\n        modalToggle(config, deleteButton);\n    };\n});\n","Magento_InventorySwatchesFrontendUi/js/swatch-renderer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n    'jquery',\n    'configurableVariationQty',\n    'jquery-ui-modules/widget'\n], function ($, configurableVariationQty) {\n    'use strict';\n\n    return function (SwatchRenderer) {\n        $.widget('mage.SwatchRenderer', SwatchRenderer, {\n\n            /** @inheritdoc */\n            _OnClick: function ($this, widget) {\n                var salesChannel = this.options.jsonConfig.channel,\n                    salesChannelCode = this.options.jsonConfig.salesChannelCode,\n                    productVariationsSku = this.options.jsonConfig.sku;\n\n                this._super($this, widget);\n                configurableVariationQty(productVariationsSku[widget.getProductId()], salesChannel, salesChannelCode);\n            }\n        });\n\n        return $.mage.SwatchRenderer;\n    };\n});\n","Magento_Ups/js/view/shipping-rates-validation.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'uiComponent',\n    'Magento_Checkout/js/model/shipping-rates-validator',\n    'Magento_Checkout/js/model/shipping-rates-validation-rules',\n    'Magento_Ups/js/model/shipping-rates-validator',\n    'Magento_Ups/js/model/shipping-rates-validation-rules'\n], function (\n    Component,\n    defaultShippingRatesValidator,\n    defaultShippingRatesValidationRules,\n    upsShippingRatesValidator,\n    upsShippingRatesValidationRules\n) {\n    'use strict';\n\n    defaultShippingRatesValidator.registerValidator('ups', upsShippingRatesValidator);\n    defaultShippingRatesValidationRules.registerRules('ups', upsShippingRatesValidationRules);\n\n    return Component;\n});\n","Magento_Ups/js/model/shipping-rates-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mageUtils',\n    'Magento_Ups/js/model/shipping-rates-validation-rules',\n    'mage/translate'\n], function ($, utils, validationRules, $t) {\n    'use strict';\n\n    return {\n        validationErrors: [],\n\n        /**\n         * @param {Object} address\n         * @return {Boolean}\n         */\n        validate: function (address) {\n            var self = this;\n\n            this.validationErrors = [];\n            $.each(validationRules.getRules(), function (field, rule) {\n                var message;\n\n                if (rule.required && utils.isEmpty(address[field])) {\n                    message = $t('Field ') + field + $t(' is required.');\n                    self.validationErrors.push(message);\n                }\n            });\n\n            return !this.validationErrors.length;\n        }\n    };\n});\n","Magento_Ups/js/model/shipping-rates-validation-rules.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return {\n        /**\n         * @return {Object}\n         */\n        getRules: function () {\n            return {\n                'postcode': {\n                    'required': true\n                },\n                'country_id': {\n                    'required': true\n                }\n            };\n        }\n    };\n});\n","Magento_Search/js/form-mini.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'underscore',\n    'mage/template',\n    'matchMedia',\n    'jquery-ui-modules/widget',\n    'jquery-ui-modules/core',\n    'mage/translate'\n], function ($, _, mageTemplate, mediaCheck) {\n    'use strict';\n\n    /**\n     * Check whether the incoming string is not empty or if doesn't consist of spaces.\n     *\n     * @param {String} value - Value to check.\n     * @returns {Boolean}\n     */\n    function isEmpty(value) {\n        return value.length === 0 || value == null || /^\\s+$/.test(value);\n    }\n\n    $.widget('mage.quickSearch', {\n        options: {\n            autocomplete: 'off',\n            minSearchLength: 3,\n            responseFieldElements: 'ul li',\n            selectClass: 'selected',\n            template:\n                '<li class=\"<%- data.row_class %>\" id=\"qs-option-<%- data.index %>\" role=\"option\">' +\n                '<span class=\"qs-option-name\">' +\n                ' <%- data.title %>' +\n                '</span>' +\n                '<span aria-hidden=\"true\" class=\"amount\">' +\n                '<%- data.num_results %>' +\n                '</span>' +\n                '</li>',\n            submitBtn: 'button[type=\"submit\"]',\n            searchLabel: '[data-role=minisearch-label]',\n            isExpandable: null,\n            suggestionDelay: 300\n        },\n\n        /** @inheritdoc */\n        _create: function () {\n            this.responseList = {\n                indexList: null,\n                selected: null\n            };\n            this.autoComplete = $(this.options.destinationSelector);\n            this.searchForm = $(this.options.formSelector);\n            this.submitBtn = this.searchForm.find(this.options.submitBtn)[0];\n            this.searchLabel = this.searchForm.find(this.options.searchLabel);\n            this.isExpandable = this.options.isExpandable;\n\n            _.bindAll(this, '_onKeyDown', '_onPropertyChange', '_onSubmit');\n\n            this.submitBtn.disabled = true;\n\n            this.element.attr('autocomplete', this.options.autocomplete);\n\n            mediaCheck({\n                media: '(max-width: 768px)',\n                entry: function () {\n                    this.isExpandable = true;\n                }.bind(this),\n                exit: function () {\n                    this.isExpandable = true;\n                }.bind(this)\n            });\n\n            this.searchLabel.on('click', function (e) {\n                // allow input to lose its' focus when clicking on label\n                if (this.isExpandable && this.isActive()) {\n                    e.preventDefault();\n                }\n            }.bind(this));\n\n            this.element.on('blur', $.proxy(function () {\n                if (!this.searchLabel.hasClass('active')) {\n                    return;\n                }\n\n                setTimeout($.proxy(function () {\n                    if (this.autoComplete.is(':hidden')) {\n                        this.setActiveState(false);\n                    } else {\n                        this.element.trigger('focus');\n                    }\n                    this.autoComplete.hide();\n                    this._updateAriaHasPopup(false);\n                }, this), 250);\n            }, this));\n\n            if (this.element.get(0) === document.activeElement) {\n                this.setActiveState(true);\n            }\n\n            this.element.on('focus', this.setActiveState.bind(this, true));\n            this.element.on('keydown', this._onKeyDown);\n            // Prevent spamming the server with requests by waiting till the user has stopped typing for period of time\n            this.element.on('input propertychange', _.debounce(this._onPropertyChange, this.options.suggestionDelay));\n\n            this.searchForm.on('submit', $.proxy(function (e) {\n                this._onSubmit(e);\n                this._updateAriaHasPopup(false);\n            }, this));\n        },\n\n        /**\n         * Checks if search field is active.\n         *\n         * @returns {Boolean}\n         */\n        isActive: function () {\n            return this.searchLabel.hasClass('active');\n        },\n\n        /**\n         * Sets state of the search field to provided value.\n         *\n         * @param {Boolean} isActive\n         */\n        setActiveState: function (isActive) {\n            var searchValue;\n\n            this.searchForm.toggleClass('active', isActive);\n            this.searchLabel.toggleClass('active', isActive);\n\n            if (this.isExpandable) {\n                this.element.attr('aria-expanded', isActive);\n                searchValue = this.element.val();\n                this.element.val('');\n                this.element.val(searchValue);\n            }\n        },\n\n        /**\n         * @private\n         * @return {Element} The first element in the suggestion list.\n         */\n        _getFirstVisibleElement: function () {\n            return this.responseList.indexList ? this.responseList.indexList.first() : false;\n        },\n\n        /**\n         * @private\n         * @return {Element} The last element in the suggestion list.\n         */\n        _getLastElement: function () {\n            return this.responseList.indexList ? this.responseList.indexList.last() : false;\n        },\n\n        /**\n         * @private\n         * @param {Boolean} show - Set attribute aria-haspopup to \"true/false\" for element.\n         */\n        _updateAriaHasPopup: function (show) {\n            if (show) {\n                this.element.attr('aria-haspopup', 'true');\n            } else {\n                this.element.attr('aria-haspopup', 'false');\n            }\n        },\n\n        /**\n         * Clears the item selected from the suggestion list and resets the suggestion list.\n         * @private\n         * @param {Boolean} all - Controls whether to clear the suggestion list.\n         */\n        _resetResponseList: function (all) {\n            this.responseList.selected = null;\n\n            if (all === true) {\n                this.responseList.indexList = null;\n            }\n        },\n\n        /**\n         * Executes when the search box is submitted. Sets the search input field to the\n         * value of the selected item.\n         * @private\n         * @param {Event} e - The submit event\n         */\n        _onSubmit: function (e) {\n            var value = this.element.val();\n\n            if (isEmpty(value)) {\n                e.preventDefault();\n            }\n\n            if (this.responseList.selected) {\n                this.element.val(this.responseList.selected.find('.qs-option-name').text());\n            }\n        },\n\n        /**\n         * Executes when keys are pressed in the search input field. Performs specific actions\n         * depending on which keys are pressed.\n         * @private\n         * @param {Event} e - The key down event\n         * @return {Boolean} Default return type for any unhandled keys\n         */\n        _onKeyDown: function (e) {\n            var keyCode = e.keyCode || e.which;\n\n            switch (keyCode) {\n                case $.ui.keyCode.HOME:\n                    if (this._getFirstVisibleElement()) {\n                        this._getFirstVisibleElement().addClass(this.options.selectClass);\n                        this.responseList.selected = this._getFirstVisibleElement();\n                    }\n                    break;\n\n                case $.ui.keyCode.END:\n                    if (this._getLastElement()) {\n                        this._getLastElement().addClass(this.options.selectClass);\n                        this.responseList.selected = this._getLastElement();\n                    }\n                    break;\n\n                case $.ui.keyCode.ESCAPE:\n                    this._resetResponseList(true);\n                    this.autoComplete.hide();\n                    break;\n\n                case $.ui.keyCode.ENTER:\n                    if (this.element.val().length >= parseInt(this.options.minSearchLength, 10)) {\n                        this.searchForm.trigger('submit');\n                        e.preventDefault();\n                    }\n                    break;\n\n                case $.ui.keyCode.DOWN:\n                    if (this.responseList.indexList) {\n                        if (!this.responseList.selected) {  //eslint-disable-line max-depth\n                            this._getFirstVisibleElement().addClass(this.options.selectClass);\n                            this.responseList.selected = this._getFirstVisibleElement();\n                        } else if (!this._getLastElement().hasClass(this.options.selectClass)) {\n                            this.responseList.selected = this.responseList.selected\n                                .removeClass(this.options.selectClass).next().addClass(this.options.selectClass);\n                        } else {\n                            this.responseList.selected.removeClass(this.options.selectClass);\n                            this._getFirstVisibleElement().addClass(this.options.selectClass);\n                            this.responseList.selected = this._getFirstVisibleElement();\n                        }\n                        this.element.val(this.responseList.selected.find('.qs-option-name').text());\n                        this.element.attr('aria-activedescendant', this.responseList.selected.attr('id'));\n                        this._updateAriaHasPopup(true);\n                        this.autoComplete.show();\n                    }\n                    break;\n\n                case $.ui.keyCode.UP:\n                    if (this.responseList.indexList !== null) {\n                        if (!this._getFirstVisibleElement().hasClass(this.options.selectClass)) {\n                            this.responseList.selected = this.responseList.selected\n                                .removeClass(this.options.selectClass).prev().addClass(this.options.selectClass);\n\n                        } else {\n                            this.responseList.selected.removeClass(this.options.selectClass);\n                            this._getLastElement().addClass(this.options.selectClass);\n                            this.responseList.selected = this._getLastElement();\n                        }\n                        this.element.val(this.responseList.selected.find('.qs-option-name').text());\n                        this.element.attr('aria-activedescendant', this.responseList.selected.attr('id'));\n                        this._updateAriaHasPopup(true);\n                        this.autoComplete.show();\n                    }\n                    break;\n                default:\n                    return true;\n            }\n        },\n\n        /**\n         * Executes when the value of the search input field changes. Executes a GET request\n         * to populate a suggestion list based on entered text. Handles click (select), hover,\n         * and mouseout events on the populated suggestion list dropdown.\n         * @private\n         */\n        _onPropertyChange: function () {\n            var searchField = this.element,\n                clonePosition = {\n                    position: 'absolute',\n                    // Removed to fix display issues\n                    // left: searchField.offset().left,\n                    // top: searchField.offset().top + searchField.outerHeight(),\n                    width: searchField.outerWidth()\n                },\n                source = this.options.template,\n                template = mageTemplate(source),\n                dropdown = $('<ul role=\"listbox\"></ul>'),\n                value = this.element.val();\n\n            this.submitBtn.disabled = true;\n\n            if (value.length >= parseInt(this.options.minSearchLength, 10)) {\n                this.submitBtn.disabled = false;\n\n                if (this.options.url !== '') { //eslint-disable-line eqeqeq\n                    $.getJSON(this.options.url, {\n                        q: value\n                    }, $.proxy(function (data) {\n                        if (data.length) {\n                            $.each(data, function (index, element) {\n                                var html;\n\n                                element.index = index;\n                                html = template({\n                                    data: element\n                                });\n                                dropdown.append(html);\n                            });\n\n                            this._resetResponseList(true);\n\n                            this.responseList.indexList = this.autoComplete.html(dropdown)\n                                .css(clonePosition)\n                                .show()\n                                .find(this.options.responseFieldElements + ':visible');\n\n                            this.element.removeAttr('aria-activedescendant');\n\n                            if (this.responseList.indexList.length) {\n                                this._updateAriaHasPopup(true);\n                            } else {\n                                this._updateAriaHasPopup(false);\n                            }\n\n                            this.responseList.indexList\n                                .on('click', function (e) {\n                                    this.responseList.selected = $(e.currentTarget);\n                                    this.searchForm.trigger('submit');\n                                }.bind(this))\n                                .on('mouseenter mouseleave', function (e) {\n                                    this.responseList.indexList.removeClass(this.options.selectClass);\n                                    $(e.target).addClass(this.options.selectClass);\n                                    this.responseList.selected = $(e.target);\n                                    this.element.attr('aria-activedescendant', $(e.target).attr('id'));\n                                }.bind(this))\n                                .on('mouseout', function (e) {\n                                    if (!this._getLastElement() &&\n                                        this._getLastElement().hasClass(this.options.selectClass)) {\n                                        $(e.target).removeClass(this.options.selectClass);\n                                        this._resetResponseList(false);\n                                    }\n                                }.bind(this));\n                        } else {\n                            this._resetResponseList(true);\n                            this.autoComplete.hide();\n                            this._updateAriaHasPopup(false);\n                            this.element.removeAttr('aria-activedescendant');\n                        }\n                    }, this));\n                }\n            } else {\n                this._resetResponseList(true);\n                this.autoComplete.hide();\n                this._updateAriaHasPopup(false);\n                this.element.removeAttr('aria-activedescendant');\n            }\n        }\n    });\n\n    return $.mage.quickSearch;\n});\n","Magento_Theme/js/cookie-status.js":"define([\n    'jquery',\n    'Magento_Ui/js/modal/modal',\n    'mage/translate'\n], function ($, modal) {\n    'use strict';\n\n    $.widget('mage.cookieStatus', {\n        options: {\n            type: 'popup',\n            responsive: true,\n            innerScroll: true,\n            autoOpen: true,\n            buttons: [{\n                text: $.mage.__('Close'),\n                class: 'cookie-status',\n\n                /**\n                 * Callback for click event\n                 */\n                click: function () {\n                    this.closeModal();\n                }\n            }]\n        },\n\n        /**\n         * Init object\n         * @private\n         */\n        _init: function () {\n\n            if (!navigator.cookieEnabled) {\n                modal(this.options, $('#cookie-status'));\n            }\n        }\n    });\n\n    return $.mage.cookieStatus;\n});\n","Magento_Theme/js/theme.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/smart-keyboard-handler',\n    'mage/mage',\n    'domReady!'\n], function ($, keyboardHandler) {\n    'use strict';\n\n    $('.cart-summary').mage('sticky', {\n        container: '#maincontent'\n    });\n\n    $('.panel.header > .header.links').clone().appendTo('#store\\\\.links');\n    $('#store\\\\.links li a').each(function () {\n        var id = $(this).attr('id');\n\n        if (id !== undefined) {\n            $(this).attr('id', id + '_mobile');\n        }\n    });\n    keyboardHandler.apply();\n});\n","Magento_Theme/js/row-builder.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * JQuery UI Widget declaration: 'mage.rowBuilder'\n *\n * @api\n */\ndefine([\n    'jquery',\n    'mage/template',\n    'jquery-ui-modules/widget'\n], function ($, mageTemplate) {\n    'use strict';\n\n    $.widget('mage.rowBuilder', {\n\n        /**\n         * options with default values for setting up the template\n         */\n        options: {\n            //Default template options\n            rowTemplate: '#template-registrant',\n            rowContainer: '#registrant-container',\n            //Row index used by the template rows.\n            rowIndex: 0,\n            //Row count: Should not be set externally\n            rowCount: 0,\n            rowParentElem: '<li></li>',\n            rowContainerClass: 'fields',\n            addRowBtn: '#add-registrant-button',\n            btnRemoveIdPrefix: 'btn-remove',\n            btnRemoveSelector: '.btn-remove',\n            rowIdPrefix: 'row',\n            //This class is added to rows added after the first one. Adds the dotted separator\n            additionalRowClass: 'add-row',\n\n            /*\n             This is provided during widget instantiation. eg :\n             formDataPost : {\"formData\":formData,\"templateFields\":['field1-name','field2-name'] }\n             -\"formData\" is the multi-dimensional array of form field values : [['a','b'],['c','b']]\n             received from the server and encoded\n             -\"templateFields\" are the input fields in the template with index suffixed after the field name\n             eg field1-name{index}\n             */\n            formDataPost: null,\n            //Default selectors for add element of a template\n            addEventSelector: 'button',\n            //Default selectors for remove markup elements of a template\n            remEventSelector: 'a',\n            //This option allows adding first row delete option and a row separator\n            hideFirstRowAddSeparator: true,\n            //Max rows - This option should be set when instantiating the widget\n            maxRows: 1000,\n            maxRowsMsg: '#max-registrant-message'\n        },\n\n        /**\n         * Initialize create\n         * @private\n         */\n        _create: function () {\n            this.rowTemplate = mageTemplate(this.options.rowTemplate);\n\n            this.options.rowCount = this.options.rowIndex = 0;\n\n            //On document ready related tasks\n            $($.proxy(this.ready, this));\n\n            //Binding template-wide events handlers for adding and removing rows\n            this.element.on(\n                'click',\n                this.options.addEventSelector + this.options.addRowBtn,\n                $.proxy(this.handleAdd, this)\n            );\n            this.element.on(\n                'click',\n                this.options.remEventSelector + this.options.btnRemoveSelector,\n                $.proxy(this.handleRemove, this)\n            );\n        },\n\n        /**\n         * Initialize template\n         * @public\n         */\n        ready: function () {\n            if (this.options.formDataPost &&\n                this.options.formDataPost.formData &&\n                this.options.formDataPost.formData.length\n            ) {\n                this.processFormDataArr(this.options.formDataPost);\n            } else if (this.options.rowIndex === 0 && this.options.maxRows !== 0) {\n                //If no form data , then add default row\n                this.addRow(0);\n            }\n        },\n\n        /**\n         * Process and loop through all row data to create preselected values. This is used for any error on submit.\n         * For complex implementations the inheriting widget can override this behavior\n         * @public\n         * @param {Object} formDataArr\n         */\n        processFormDataArr: function (formDataArr) {\n            var formData = formDataArr.formData,\n                templateFields = formDataArr.templateFields,\n                formRow,\n                i, j;\n\n            for (i = this.options.rowIndex = 0; i < formData.length; this.options.rowIndex = i++) {\n                this.addRow(i);\n\n                formRow = formData[i];\n\n                for (j = 0; j < formRow.length; j++) {\n                    this.setFieldById(templateFields[j] + i, formRow[j]);\n                }\n            }\n\n        },\n\n        /**\n         * Initialize and create markup for template row. Add it to the parent container.\n         * The template processing will substitute row index at all places marked with _index_ in the template\n         * using the template\n         * @public\n         * @param {Number} index - current index/count of the created template. This will be used as the id\n         * @return {*}\n         */\n        addRow: function (index) {\n            var row = $(this.options.rowParentElem),\n                tmpl;\n\n            row.addClass(this.options.rowContainerClass).attr('id', this.options.rowIdPrefix + index);\n\n            tmpl = this.rowTemplate({\n                data: {\n                    _index_: index\n                }\n            });\n\n            $(tmpl).appendTo(row);\n\n            $(this.options.rowContainer).append(row).trigger('contentUpdated');\n\n            row.addClass(this.options.additionalRowClass);\n\n            //Remove 'delete' link and additionalRowClass for first row\n            if (this.options.rowIndex === 0 && this.options.hideFirstRowAddSeparator) {\n                $('#' + this._esc(this.options.btnRemoveIdPrefix) + '0').remove();\n                $('#' + this._esc(this.options.rowIdPrefix) + '0').removeClass(this.options.additionalRowClass);\n            }\n\n            this.maxRowCheck(++this.options.rowCount);\n\n            return row;\n        },\n\n        /**\n         * Remove return item information row\n         * @public\n         * @param {*} rowIndex - return item information row index\n         * @return {Boolean}\n         */\n        removeRow: function (rowIndex) {\n            $('#' + this._esc(this.options.rowIdPrefix) + rowIndex).remove();\n            this.maxRowCheck(--this.options.rowCount);\n\n            return false;\n        },\n\n        /**\n         * Function to check if maximum rows are exceeded and render/hide maxMsg and Add btn\n         * @public\n         * @param {Number} rowIndex\n         */\n        maxRowCheck: function (rowIndex) {\n            var addRowBtn = $(this.options.addRowBtn),\n                maxRowMsg = $(this.options.maxRowsMsg);\n\n            //liIndex starts from 0\n            if (rowIndex >= this.options.maxRows) {\n                addRowBtn.hide();\n                maxRowMsg.show();\n            } else if (addRowBtn.is(':hidden')) {\n                addRowBtn.show();\n                maxRowMsg.hide();\n            }\n        },\n\n        /**\n         * Set the value on given element\n         * @public\n         * @param {String} domId\n         * @param {String} value\n         */\n        setFieldById: function (domId, value) {\n            var x = $('#' + this._esc(domId));\n\n            if (x.length) {\n\n                if (x.is(':checkbox')) {\n                    x.attr('checked', true);\n                } else if (x.is('option')) {\n                    x.attr('selected', 'selected');\n                } else {\n                    x.val(value);\n                }\n            }\n        },\n\n        /**\n         * Delegated handler for adding a row\n         * @public\n         * @return {Boolean}\n         */\n        handleAdd: function () {\n            this.addRow(++this.options.rowIndex);\n\n            return false;\n        },\n\n        /**\n         * Delegated handler for removing a selected row\n         * @public\n         * @param {Object} e - Native event object\n         * @return {Boolean}\n         */\n        handleRemove: function (e) {\n            this.removeRow($(e.currentTarget).closest('[id^=\"' + this.options.btnRemoveIdPrefix + '\"]')\n                .attr('id').replace(this.options.btnRemoveIdPrefix, ''));\n\n            return false;\n        },\n\n        /**\n         * Utility function to add escape chars for jquery selector strings\n         * @private\n         * @param {String} str - String to be processed\n         * @return {String}\n         */\n        _esc: function (str) {\n            return str ? str.replace(/([ ;&,.+*~\\':\"!\\^$\\[\\]()=>|\\/@])/g, '\\\\$1') : str;\n        }\n    });\n\n    return $.mage.rowBuilder;\n});\n","Magento_Theme/js/view/add-home-breadcrumb.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* eslint-disable max-nested-callbacks, no-undef */\ndefine([\n    'jquery',\n    'Magento_Theme/js/model/breadcrumb-list',\n    'mage/translate'\n], function ($, breadcrumbList) {\n    'use strict';\n\n    /**\n     * @return {Object}\n     */\n    var homeCrumb = function () {\n        return {\n            name: 'home',\n            label: $.mage.__('Home'),\n            title: $.mage.__('Go to Home Page'),\n            link: BASE_URL || ''\n        };\n    };\n\n    return function (breadcrumb) {\n\n        breadcrumbList.unshift(homeCrumb());\n\n        return breadcrumb;\n    };\n});\n","Magento_Theme/js/view/messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n    'jquery',\n    'uiComponent',\n    'Magento_Customer/js/customer-data',\n    'underscore',\n    'escaper',\n    'jquery/jquery-storageapi'\n], function ($, Component, customerData, _, escaper) {\n    'use strict';\n\n    return Component.extend({\n        defaults: {\n            cookieMessages: [],\n            cookieMessagesObservable: [],\n            messages: [],\n            allowedTags: ['div', 'span', 'b', 'strong', 'i', 'em', 'u', 'a']\n        },\n\n        /**\n         * Extends Component object by storage observable messages.\n         */\n        initialize: function () {\n            this._super().observe(\n                [\n                    'cookieMessagesObservable'\n                ]\n            );\n\n            // The \"cookieMessages\" variable is not used anymore. It exists for backward compatibility; to support\n            // merchants who have overwritten \"messages.phtml\" which would still point to cookieMessages instead of the\n            // observable variant (also see https://github.com/magento/magento2/pull/37309).\n            this.cookieMessages = _.unique($.cookieStorage.get('mage-messages'), 'text');\n            this.cookieMessagesObservable(this.cookieMessages);\n\n            this.messages = customerData.get('messages').extend({\n                disposableCustomerData: 'messages'\n            });\n\n            $.mage.cookies.set('mage-messages', '', {\n                samesite: 'strict',\n                domain: ''\n            });\n        },\n\n        /**\n         * Prepare the given message to be rendered as HTML\n         *\n         * @param {String} message\n         * @return {String}\n         */\n        prepareMessageForHtml: function (message) {\n            return escaper.escapeHtml(message, this.allowedTags);\n        },\n        purgeMessages: function () {\n            if (!_.isEmpty(this.messages().messages)) {\n                customerData.set('messages', {});\n            }\n        }\n    });\n});\n","Magento_Theme/js/view/breadcrumbs.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n    'jquery',\n    'mage/template',\n    'Magento_Theme/js/model/breadcrumb-list',\n    'text!Magento_Theme/templates/breadcrumbs.html',\n    'jquery-ui-modules/widget'\n], function ($, mageTemplate, breadcrumbList, tpl) {\n    'use strict';\n\n    /**\n     * Breadcrumb Widget.\n     */\n    $.widget('mage.breadcrumbs', {\n\n        /** @inheritdoc */\n        _init: function () {\n            this._super();\n            this._render();\n        },\n\n        /**\n         * Render breadcrumb.\n         *\n         * @private\n         */\n        _render: function () {\n            var html,\n                crumbs = breadcrumbList,\n                template = mageTemplate(tpl);\n\n            this._decorate(crumbs);\n\n            html = template({\n                'breadcrumbs': crumbs\n            });\n\n            if (html.length) {\n                $(this.element).html(html);\n            }\n        },\n\n        /**\n         * Decorate list.\n         *\n         * @param {Array} list\n         * @private\n         */\n        _decorate: function (list) {\n\n            if (list.length) {\n                list[0].first = true;\n            }\n\n            if (list.length > 1) {\n                list[list.length - 1].last = true;\n            }\n        }\n    });\n\n    return $.mage.breadcrumbs;\n});\n","Magento_Theme/js/model/breadcrumb-list.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n    'use strict';\n\n    return [];\n});\n"}
}});